filter array depending on it's type

57 Views Asked by At

I'm new to typescript ... I have an array which it's type is a union of two types typeA[] | typeB[] but I want to filter depending on the type of the object

interface TypeA {
  attribute1: string
  attribute2: string
}

interface TypeB {
  attribute3: string
  attribute4: string
}

function fitlerFunc(obj: TypeA[] | TypeB[]) {
  if(/*obj is TypeA */) {
    return obj.filter(item => item.attribute1 === 'test')
  }

  if(/*obj is TypeB */) {
    return obj.filter(item => item.attribute3 === 'something')
  }
}

or if there is a way to know which type of array I receive

1

There are 1 best solutions below

0
jsejcksn On

An plain array itself has no attributes that can be used to discriminate its elements' types.

However, you can use a functional type guard to validate at runtime that the array's elements conform to the expected type, then safely perform the property access operation inside the filter callback function:

TS Playground

function arrayItemsHaveProperty<P extends PropertyKey>(
  array: object[],
  prop: P,
): array is Record<P, unknown>[] {
  return array.every((o) => prop in o);
}

interface TypeA {
  attribute1: string;
  attribute2: string;
}

interface TypeB {
  attribute3: string;
  attribute4: string;
}

function fitlerFunc(obj: TypeA[] | TypeB[]) {
  if (arrayItemsHaveProperty(obj, "attribute1")) {
    return obj.filter((item) => item.attribute1 === "test");
    //     ^? (parameter) obj: TypeA[]
  }
  return obj.filter((item) => item.attribute3 === "something");
  //     ^? (parameter) obj: TypeB[]
}

Note that this approach prefers simpler syntax over performance (two iterations of the array) — you could do it in a single iteration, but type assertions would be required. The trade-off depends on the details of your actual use case.