TypeScript联合类型参数的函数返回类型自动校验问题
问题分析与解决方案
为什么原代码不报错?
TypeScript对对象字面量的超额属性检查(即检测未定义属性)仅在以下场景触发:
- 对象字面量直接赋值给明确类型的变量
- 对象字面量作为函数参数直接传入
当你把函数作为参数传给myFunction时,函数的返回值会被推断为MyType的兼容类型——返回的对象字面量会被视为MyType & { unrecognisedProperty: string },这个类型结构上兼容MyType,所以编译器不会报错。
无需显式指定返回类型的解决方案
方案1:使用泛型约束实现严格检查
修改myFunction的定义,通过泛型约束让编译器对传入的函数做更严格的类型校验:
type MyType = { foo: string bar: number } type MyFuncType = (input: string) => MyType // 用泛型T约束为MyFuncType的子类型 function myFunction<T extends MyFuncType>(input: string | T) { if (typeof input === 'function') { // do things } else { // do other things } } function test() { myFunction((id) => { return { foo: 'foo', bar: 123, unrecognisedProperty: 'hello' // 现在会触发错误:类型"{ foo: string; bar: number; unrecognisedProperty: string; }"不能赋值给类型"MyType" } }) }
原理:泛型参数T在函数参数位置属于逆变位置,TypeScript会对逆变位置的类型做严格检查,不允许带额外属性的兼容类型通过。
方案2:利用satisfies关键字(TS 4.9+)
如果你不想修改myFunction的定义,也可以在传入函数前用satisfies约束函数类型,同时保留参数的类型推断:
function test() { const func = ((id) => { return { foo: 'foo', bar: 123, unrecognisedProperty: 'hello' // 触发错误 } }) satisfies MyFuncType; myFunction(func); }
这种方式不需要改动原函数,只是在传入前先对函数做类型校验。
内容的提问来源于stack exchange,提问作者Ryan
相关产品推荐
相关产品推荐

