目录
- ts封装类型判断的问题
- 类型谓词
- TypeScript的“控制流分析”
ts封装类型判断的问题
在union.d.ts 中 全局声明一个 DataType
declare type DataType =| "RegExp"| "Object"| "Array"| "Function"| "String"| "Boolean"| "Number"| "Void"| "Null"| "Undefined";
然后在utils文件里封装一个用于判断类型的函数
/*** @description 判断値的类型* @param {any} value 要检查的值* @param {DataType} type 要检查的类型* @returns Boolean*/
export function isType(value: any, type: DataType) {if (type === "Void") {return value === null || value === undefined;}//Object 是一个构造函数,直接调用Object.toString,会在原型链上查找,而会先找到Function.prototype,而Function.prototype.toString()的作用不是用来检查类型的// 而Object.prototype 是通过 new Object() 创造的实例的原型//call:是Function.prototype 的方法,改变thisconst res = Object.prototype.toString.call(value);//[object Null] 、 [object Number]等return res === `[object ${type}]`;
}
然后我准备封装一个用于过滤对象属性的方法,此时用到了 isType,这时问题就出来了。
export function getFilterObj(source: Record<string, any>,exclude: string | string[]
) {if (isType(exclude, "String")) {/** ts报错 exclude 类型“string | string[]”上不存在属性“split”。 * 由于此处exclude依然可能是 string[] 类型,所以不能用字符串的方法。*/const { [exclude]: omitted, ...rest } = source;return rest;} else if (isType(exclude, "Array")) {...}
}
我自己封装的方法,ts在外部无法得知value是什么类型,因为返回值是Boolean类型。
类型谓词
类型谓词是一个特殊的函数签名,它在返回布尔值的同时,还告诉TypeScript在函数返回true时,某个参数的具体类型。这是通过在函数签名中使用 参数名 i s \color{orange}is is 目标类型 来实现的。
在返回值为 true 时,额外传递一些信息给调用者
/** 类型谓词 value is string */
// 返回值为true时,形参类型为string 类型
function isString(value: any): value is string {return typeof value === "string";
}function getName(source: string | string[]) {if (isString(source)) {// 类型校验通过,source为string 类型source.split("");}
}
但我们注意到,typeof 也可以ts校验通过
function getName(source: string | string[]) {if (typeof source === "string") {// 类型校验通过,source为string 类型source.split("");}
}
这里提到一点,就是 js 是运行时执行的,也就是说js的代码在编译时无法得知 source是什么类型,而ts是编译时执行的,而在编译时,source的类型就是自己写定的 string|string[] 类型。
TypeScript的“控制流分析”
但之所以ts最终校验通过,是因为 TypeScript的“控制流分析”,当你在TypeScript代码中使用 if (typeof source === “string”) { … } 这样的条件语句时,TypeScript的类型检查器(Type Checker)会利用这个条件来推断在条件块内部 source 变量的类型。
这是TypeScript的“控制流分析”(Control Flow Analysis)功能的一部分。 T y p e S c r i p t 的类型检查器会分析代码中的条件语句、循环等结构 \color{orange} TypeScript的类型 检查器会分析代码中的条件语句、循环等结构 TypeScript的类型检查器会分析代码中的条件语句、循环等结构,并根据这些结构中的条件来推断变量的类型。在这个例子中,当TypeScript看到 if (typeof source === “string”) { … } 时,它会在条件块内部将 source 的类型推断为 string,即使这个检查实际上是在运行时进行的。
这种类型推断只在语句内部有用