起源是在 ts 项目里有描述 Filter 返回类型的需求, 省略后的代码如下
type Item = { type: Type.A };
enum Type {
A,
B,
}
const foo = <T extends Item>(arr: T[]) => {
return arr;
};
const arr: { type: Type }[] = [
{
type: Type.A,
},
{
type: Type.B,
},
];
const result = foo(arr.filter<Item>((item) => item.type === Type.A));
由于 foo 的入参只接受 arr 过滤后的某种类型,默认情况下 ts 会报错:
于是我开始查看 Array 的 filter 声明描述:
interface Array<T> {
// ...
/**
* Returns the elements of an array that meet the condition specified in a callback function.
* @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the predicate function. If thisArg is omitted, undefined is used as the this value.
*/
filter<S extends T>(
predicate: (value: T, index: number, array: T[]) => value is S,
thisArg?: any
): S[];
/**
* Returns the elements of an array that meet the condition specified in a callback function.
* @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the predicate function. If thisArg is omitted, undefined is used as the this value.
*/
filter(
predicate: (value: T, index: number, array: T[]) => unknown,
thisArg?: any
): T[];
}
什么是 is
关键字?
is 是 TypeScript 语法里的类型谓词,表示是否属于某个类型,可以有效地缩小类型范围。
使用类型谓词
A predicate takes the form parameterName is Type, where parameterName must be the name of a parameter from the current function signature.1
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined;
}
类型谓词可以在条件语句中识别:
// Both calls to 'swim' and 'fly' are now okay.
let pet = getSmallPet();
if (isFish(pet)) {
pet.swim();
} else {
pet.fly();
}
我发现,在使用typeof
是做类型判断时,ts 会自动识别返回的类型,无需使用类型谓词
最后,回到我的例子里补充了类型谓词后的代码则是:
type Item = { type: Type.A };
enum Type {
A,
B,
}
const foo = <T extends Item>(arr: T[]) => {
return arr;
};
const arr: { type: Type }[] = [
{
type: Type.A,
},
{
type: Type.B,
},
];
const result = foo(
arr.filter<Item>((item): item is Item => item.type === Type.A)
);
分享一下 TypeScript 官网的速查表2,可以帮助快速查找常见 TypeScript 代码的语法: