如何让TypeScript在动态调度器中自动推断类型?
TypeScript动态调度器类型匹配错误解决
我尝试构建一个根据动物类型自动调用对应行为函数的动态调度器,代码如下:
enum AnimalType { Rabbit = 'Rabbit', Duck = 'Duck', } interface RabbitInput { animalType: AnimalType.Rabbit; food: string; } interface DuckInput { animalType: AnimalType.Duck; swim_speed: number; } type AnimalInput = RabbitInput | DuckInput type AnimalFunctionMap = { [AnimalType.Duck]: (input: DuckInput) => Promise<any>; [AnimalType.Rabbit]: (input: RabbitInput) => Promise<any>; }; const eat = async (input: RabbitInput) => { return { 'status': 'satisfied' }; } const swim = async(input: DuckInput) => { return { 'status': 'fast' }; } const animalFunctions: AnimalFunctionMap = { [AnimalType.Duck]: swim, [AnimalType.Rabbit]: eat, }; function isRabbitInput(input: AnimalInput): input is RabbitInput { return input.animalType === AnimalType.Rabbit } function isDuckInput(input: AnimalInput): input is DuckInput { return input.animalType === AnimalType.Duck } const applyAnimalBehaviour = async (input: AnimalInput): Promise<any> => { const animalFunction = animalFunctions[input.animalType]; if (animalFunction) { if (isRabbitInput(input)) { return await animalFunction(input); } else if (isDuckInput(input)) { return await animalFunction(input); } else { throw new Error(`Unsupported animal type.`); } } else { throw new Error(`No animal function found for type.`); } };
但运行时出现了如下类型错误:
Argument of type 'DuckInput' is not assignable to parameter of type 'never'. The intersection 'DuckInput & RabbitInput' was reduced to 'never' because property 'animalType' has conflicting types in some constituents.(2345)
错误原因
TypeScript无法自动关联animalFunctions[input.animalType]的函数类型与input的具体类型。当你通过索引访问获取函数时,TS会将其推断为所有对应函数的联合类型,而联合类型的函数调用要求参数是所有函数参数的交集。由于DuckInput和RabbitInput的animalType类型冲突,它们的交集是never,因此出现报错。
解决方案
方案1:使用switch case(最直观类型安全)
直接通过switch匹配动物类型,TS会自动识别每个case中input的具体类型,无需额外类型守卫:
const applyAnimalBehaviour = async (input: AnimalInput): Promise<any> => { switch(input.animalType) { case AnimalType.Rabbit: return await animalFunctions[AnimalType.Rabbit](input); case AnimalType.Duck: return await animalFunctions[AnimalType.Duck](input); default: throw new Error(`Unsupported animal type.`); } };
方案2:类型断言简化调用
通过类型断言告诉TS当前函数的参数类型与input匹配:
const applyAnimalBehaviour = async (input: AnimalInput): Promise<any> => { const animalFunction = animalFunctions[input.animalType]; if (animalFunction) { return await (animalFunction as (input: typeof input) => Promise<any>)(input); } else { throw new Error(`No animal function found for type.`); } };
方案3:泛型强关联类型
用泛型约束输入类型,让TS能正确推断函数与参数的匹配关系:
const applyAnimalBehaviour = async <T extends AnimalInput>(input: T): Promise<any> => { const animalFunction = animalFunctions[input.animalType] as (input: T) => Promise<any>; if (animalFunction) { return await animalFunction(input); } else { throw new Error(`No animal function found for type.`); } };
内容的提问来源于stack exchange,提问作者Letharion
相关产品推荐
相关产品推荐

