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 的方法,改变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,即使这个检查实际上是在运行时进行的。

这种类型推断只在语句内部有用

  • 28
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值