前言
在写 ts 的时候,借助类型推导,我们可以不用费劲的为每个变量、函数定义类型,但类型推导也不是万能的,有时候并不能准确的进行类型的控制,所以我们需要自己指定类型,所以 is 关键字显得尤为重要。
正文
例 1
const getType = (val: unknown) => Object.prototype.toString.call(val).slice(8, -1).toLowerCase()
const isString = (val: unknown) => getType(val) === 'string'
可以看出如果 isString 返回了 true ,那么可以知道 val 是字符串,但编译器不知道,所以 val 依旧是 unknown ,也就不会有 toUpperCase 方法:
const foo = (val: unknown) => isString(val) ? val.toUpperCase() : val
如果不讲究的话可以用断言:
const foo = (val: unknown) => isString(val) ? (val as string).toUpperCase() : val
但上述断言是治标不治本的行为,我们可以通过 is 关键字更为精准的控制类型,以下代码相当于告诉编译器,如果返回结果为 true,则代表 val 是 string 类型:
const isString = (val: unknown): val is string => getType(val) === 'string'
例 2
可以借助泛型对复杂类型数据进行更深层次的类型控制
const getType = (val: unknown) => Object.prototype.toString.call(val).slice(8, -1).toLowerCase()
const isArray = <T>(val: unknown): val is T[] => getType(val) === 'array'
// 这里我们通过泛型说明如果 isArray 返回了 true ,意味着 val 是由 string 构成的数组
const foo = (val: unknown) => isArray<string>(val) ? val.map(item => item.toLowerCase()) : val
结语
以上内容如有不正之处,望各位指正!