如何确保TypeScript类型收窄在返回值上生效?
为什么函数内部的类型收窄无法传递给调用方的返回值类型?
我有一个返回对象的函数,在函数内部已经对对象做了类型收窄,但调用方使用返回值时,收窄后的类型并未生效,代码示例如下:
type X = { prop: undefined | string }; function f(x: X) { if (typeof x.prop === 'undefined') throw new TypeError(); // 将"prop"收窄为非undefined类型 x.prop.charAt(0); // <- 这里没有错误,类型收窄生效了 return { x }; } f({ prop: undefined }).x.prop.charAt(0); // <- 这里报错说"prop"可能为undefined, // 但实际上f()已经把它收窄为非undefined类型了
问题原因
TypeScript的类型收窄是局部性的,它只会在当前代码块内跟踪类型变化,不会自动将这种收窄后的类型信息提升到函数的返回值类型中。函数f的返回值默认被推断为{ x: X },而非{ x: { prop: string } },所以调用方拿到的x仍然是原始的X类型,不知道内部已经排除了prop为undefined的情况。
解决方案
- 明确指定函数返回类型
直接定义收窄后的返回类型,告诉TypeScript函数返回的对象中x的prop一定是字符串:
type X = { prop: undefined | string }; // 定义收窄后的类型 type XWithDefinedProp = { prop: string }; function f(x: X): { x: XWithDefinedProp } { if (typeof x.prop === 'undefined') throw new TypeError(); x.prop.charAt(0); return { x } as { x: XWithDefinedProp }; } f({ prop: undefined }).x.prop.charAt(0); // 不再报错
- 返回时使用类型断言
如果不想单独定义类型,可直接在返回时将x断言为收窄后的类型:
type X = { prop: undefined | string }; function f(x: X) { if (typeof x.prop === 'undefined') throw new TypeError(); x.prop.charAt(0); return { x: x as { prop: string } }; } f({ prop: undefined }).x.prop.charAt(0); // 正常无报错
- 使用自定义类型守卫函数
把类型检查逻辑抽成类型守卫函数,让TypeScript全局识别这种类型收窄:
type X = { prop: undefined | string }; // 类型守卫函数:返回true时,x的类型会被收窄为{ prop: string } function hasDefinedProp(x: X): x is { prop: string } { return typeof x.prop !== 'undefined'; } function f(x: X) { if (!hasDefinedProp(x)) throw new TypeError(); x.prop.charAt(0); return { x }; } f({ prop: undefined }).x.prop.charAt(0); // 无报错
内容的提问来源于stack exchange,提问作者mrh1997
相关产品推荐
相关产品推荐

