Issue
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)
Solution
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')
Answered By – Titian Cernicova-Dragomir
Answer Checked By – Dawn Plyler (BugsFixing Volunteer)