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 的方法,改变this
const 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,即使这个检查实际上是在运行时进行的。
这种类型推断只在语句内部有用