TypeScript 中文教程之缩小----翻译自TS官方
🔯 Narrowing概念:字面意思是缩小,可以理解为类型细化。
TS官方在这里做了很详细的说明,文字较多,简单以图片概括:
🔯 typeof type guards 类型防护过程,可以通过 typeof 检测出大部分类型并对比预设类型,如:
- "string"
- "number"
- "boolean"
- "symbol"
- "undefined"
- "object"
- "function"
但是对于特殊的对象,比如 null ,typeof 就无能为力了,因为 typeof null === 'object'。看个例子:
function printAll(strs: string | string[] | null) {
if (typeof strs === "object") {
for (const s of strs) { //for of 遍历数组中的元素
// 🤢 Object is possibly 'null'.Object is possibly 'null'.
console.log(s);
}
} else if (typeof strs === "string") {
console.log(strs);
} else {
// do nothing
}
}
🔯 布尔值运算
因为对下列这些对象进行布尔运算返回都是 false :
- 0
- NaN
- null
- undefined
- ""
所以上面的例子可以先对 null 进行判断然后执行后面的逻辑
function printAll(strs: string | string[] | null) {
if (strs && typeof strs === "object") {
for (const s of strs) { //for of 遍历数组中的元素
// 😊 strs 如果是null则跳过这个分支
console.log(s);
}
} else if (typeof strs === "string") {
console.log(strs);
}
}
👀 思考以下两个方法有何不同?
function printAll(strs: string | string[] | null) {
if (strs) {
if (typeof strs === "object") {
for (const s of strs) {
console.log(s);
}
} else if (typeof strs === "string") {
console.log(strs);
}
}
}
function anotherPrintAll(strs: string | string[] | null) {
if (strs !== null) {
if (typeof strs === "object") {
for (const s of strs) {
console.log(s);
}
} else if (typeof strs === "string") {
console.log(strs);
}
}
}
🔯 使用 in 操作符进行类型缩小
js中使用in操作符可以判单一个对象是否拥有某个属性,TS 也将in作为缩小类型判断的方式。
比如在一个联合类型中,可以这样判断 'value' in x,
x可能是 type Animal = Fish | Bird, value 表示 x 中的某一个字面量(可能是Fish或者Bird)
type Fish = { swim: () => void };
type Bird = { fly: () => void };
function move(animal: Fish | Bird) {
if ("swim" in animal) {
return animal.swim();
}
return animal.fly();
}
🔯 使用类型谓词
有时候我们希望从更多角度控制类型的检测,定义一个自定义的类型保护,即定义一个返回类型的方法就是一个类型谓词。
例如:
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined;
}
return (pet as Fish).swim !== undefined;
}
pet is Fish 就是一个类型谓词。定义一个类型谓词的方式:参数名称 is 类型名称,参数名称必须是当前方法的一个参数。
任何时候,只要isFish携带参数调用了,如果原始类型兼容,TypeScript会将该变量缩小到该特定类型。
例如:
let pet = getSmallPet();
if(isFish(pet)) {
pet.swim();
} else {
pet.fly();
}
pet.swim();
} else {
pet.fly();
}
TS可以在if分支处得知pet是一条能游的Fish,当然了在else分支处pet被当作一只能飞的Bird。
当然了,你可以使用isFish这个类型保护去过滤一个包含了飞鸟与鱼的数组,最后得到一个尽是鱼的数组。
例如:
const zoo: (Fish | Bird)[] = [getSmallPet(), getSmallPet(), getSmallPet()];
const underWater: Fish[] = zoo.filter(isFish)
posted on 2022-01-07 17:51 Deflect-o-Bot 阅读(163) 评论(0) 编辑 收藏 举报