为什么TypeScript中接收返回泛型的函数不具备完整类型安全?
问题原因
这个本质是TypeScript的多余属性检查触发规则和结构化类型兼容共同作用的结果:
- TypeScript默认采用结构化类型系统,只要一个类型包含目标类型所有必填的属性,就算多了其他属性,也会被认为是目标类型的子类型,兼容目标类型的赋值要求。
- 仅当你把对象字面量直接赋值给明确标注了类型的变量/参数/返回值时,才会触发多余属性检查,禁止出现目标类型未定义的属性。
第一种写法的执行逻辑
你调用foo<Result>(() => { ... })时:
- 泛型
T被显式指定为Result,因此参数f的类型被推导为() => Result - 你传入的箭头函数没有显式标注返回类型,TS会优先推导这个函数的返回值类型:
{ bar: number, baz: number, FOO: number } - TS判断这个推导出来的类型是否满足
() => Result的要求:因为推导出来的类型包含Result的所有必填属性bar,属于Result的子类型,兼容判断通过,不会触发多余属性检查,所以不会报错。
第二种写法的执行逻辑
你给箭头函数显式标注了返回类型(): Result:
- 此时箭头函数的返回值类型已经被明确指定为
Result - 你返回的对象字面量是直接赋值给明确类型的返回值,触发多余属性检查,检测到
FOO不属于Result定义的属性,直接报错,符合你的预期。
解决方案
如果希望第一种写法也能获得严格的多余属性校验,可以修改泛型函数的定义,增加精确类型判断:
type Exact<T, U> = U extends T ? (T extends U ? U : never) : never; const foo = <T,>(f: () => Exact<T, ReturnType<typeof f>>) => { return f() as T; };
修改后再调用foo<Result>(...)时,多余的baz和拼写错误的FOO都会触发类型报错。
内容的提问来源于stack exchange,提问作者ilbrando
相关产品推荐
相关产品推荐

