为什么TypeScript中布尔值或普通函数无法作为类型守卫生效?
TypeScript类型守卫常见问题解析
为什么自定义的typeGuard函数会报错?
你写的typeGuard只是一个返回布尔值的普通函数,TypeScript无法从它的返回值里推断出参数的具体类型——默认情况下,普通函数的布尔返回结果不会触发类型收窄。另外你还犯了个笔误:函数参数是val,但你判断的是外层的value变量,不过即使修正这个问题,普通布尔返回值的函数依然无法成为类型守卫。
什么样的类型守卫才有效?
要让函数或表达式能触发类型收窄,得满足TypeScript的类型守卫规则,常见的有效类型守卫包括:
1. 原生类型检查表达式
直接使用typeof、instanceof、in等原生语法做判断,TypeScript内置了对这些表达式的类型推断能力:
// typeof判断基本类型 typeof value === 'string' ? functionStr(value) : functionNum(value) // instanceof判断类实例 class Foo {} const bar: Foo | string = new Foo(); if (bar instanceof Foo) { // bar在这里被收窄为Foo类型 } // in判断对象属性 type ObjA = { a: string }; type ObjB = { b: number }; const obj: ObjA | ObjB = { a: 'test' }; if ('a' in obj) { // obj在这里被收窄为ObjA类型 }
2. 带类型谓词的自定义函数
给函数的返回值添加类型谓词(val is Type格式),明确告诉TypeScript:当函数返回true时,参数val的类型是指定的Type。修正你的示例:
type SomeType = string | number const functionStr = (val: string) => { /* ... */ } const functionNum = (val: number) => { /* ... */ } let value: SomeType; // 带类型谓词的类型守卫函数 const isString = (val: SomeType): val is string => { return typeof val === 'string'; } // 现在TypeScript能正确收窄value的类型 isString(value) ? functionStr(value) : functionNum(value)
3. 类型断言函数
通过asserts val is Type声明的函数,会在类型不匹配时抛出错误,调用后TypeScript会认定变量是指定类型:
function assertIsString(val: unknown): asserts val is string { if (typeof val !== 'string') { throw new Error('Value is not a string'); } } // 调用后value会被收窄为string类型 assertIsString(value); functionStr(value);
另外,像true ? ... : ...这种固定布尔值的判断,因为没有携带任何类型相关的推断信息,TypeScript无法确定分支里变量的具体类型,所以会报错。
内容的提问来源于stack exchange,提问作者supersize
相关产品推荐
相关产品推荐

