Home > Enterprise >  Use property to filter data while filtering the union type of the property
Use property to filter data while filtering the union type of the property

Time:03-16

I am trying to filter the data by code property that the value is not equal to 'd'. JS code is fine. I expect code property in the filtered data type is 'a' | 'b' | 'c'.

type Code = 'a' | 'b' | 'c' | 'd';
interface Data {
  code: Code;
}

const data: Data[] = [{ code: 'a' }, { code: 'b' }, { code: 'c' }, { code: 'd' }]

interface Filtered {
  code: Exclude<Code, 'd'>;
}
const filtered: Filtered[] = data.filter(v => v.code !== 'd')

Got error:

Type 'Data[]' is not assignable to type 'Filtered[]'.
  Type 'Data' is not assignable to type 'Filtered'.
    Types of property 'code' are incompatible.
      Type 'Code' is not assignable to type '"a" | "b" | "c"'.
        Type '"d"' is not assignable to type '"a" | "b" | "c"'.(2322)

TypeScript Playground

CodePudding user response:

Typescript will not use v.code !== 'd' to change the type of the item in the array.

You can create a custom type guard to narrow the type of the item, but this is basically you taking control and telling the compiler that that check you perform will narrow the item type, it is not actually enforced that your check narrows the type correctly.

const filtered: Filtered[] = data.filter((v): v is Filtered => v.code !== 'd')

// v is Filtered is not checked
const filteredBad: Filtered[] = data.filter((v): v is Filtered => v.code !== 'a')

Playground Link

  • Related