TypeScript无法自动识别条件函数参数类型,如何解决?
问题描述
我尝试创建一个带有条件参数的函数,根据第一个参数的取值,第二个参数的类型会对应变化。但在条件判断代码块中,TypeScript无法自动断言出正确的参数类型,请问该如何解决?
我的代码如下:
type User = { name: string } type Animal = { species: string } function get<T extends 'user' | 'animal'>(modelType: T, model: T extends 'user' ? User : Animal) { if (modelType === 'user') { model.name // Property 'name' does not exist on type 'User | Animal'. } else { model.species // Property 'species' does not exist on type 'User | Animal'. } }
按照条件类型逻辑,当判断modelType为'user'时,TypeScript应该识别出model为User类型,但实际却报错。
解决方案
方法一:使用函数重载
这是最直观的解决方式,为每种参数组合定义单独的重载签名,TypeScript能准确推断代码块内的参数类型:
type User = { name: string } type Animal = { species: string } // 重载签名:定义两种参数组合 function get(modelType: 'user', model: User): void; function get(modelType: 'animal', model: Animal): void; // 实现签名:处理通用逻辑 function get(modelType: 'user' | 'animal', model: User | Animal) { if (modelType === 'user') { model.name // 正确推断为User类型 } else { model.species // 正确推断为Animal类型 } }
方法二:自定义类型谓词
通过类型谓词函数,手动建立modelType和model的类型关联:
type User = { name: string } type Animal = { species: string } // 类型谓词函数:判断model是否为User类型 function isUser(modelType: string, model: User | Animal): model is User { return modelType === 'user'; } function get<T extends 'user' | 'animal'>(modelType: T, model: T extends 'user' ? User : Animal) { if (isUser(modelType, model)) { model.name // 正确推断为User类型 } else { model.species // 正确推断为Animal类型 } }
方法三:重构为联合类型参数
将两个参数合并为一个联合类型的对象,让TypeScript自动关联参数间的类型关系:
type User = { name: string } type Animal = { species: string } // 定义联合类型的参数对象 type GetParams = | { modelType: 'user', model: User } | { modelType: 'animal', model: Animal } function get(params: GetParams) { if (params.modelType === 'user') { params.model.name // 正确推断为User类型 } else { params.model.species // 正确推断为Animal类型 } }
内容的提问来源于stack exchange,提问作者Gustavo Carvalho
相关产品推荐
相关产品推荐

