如何让TypeScript根据输入参数类型条件推断返回值类型?
TypeScript根据输入类型精准推断返回类型的解决方案
问题场景
需要实现一个函数,根据options.input的类型返回对应结果:当input属于TextType时返回string,属于CheckType时返回string[]。现有类型定义如下:
const TextInputTypes = <const>[ "text", "number", "password", "email", "tel", "url", "search", "color", "date", "time", "datetime-local", "month", "week", "range", "file", ]; const CheckboxTypes = <const>["checkbox", "radio"]; const SelectTypes = <const>["select"]; type TextType = (typeof TextInputTypes)[number]; type CheckType = (typeof CheckboxTypes)[number] | (typeof SelectTypes)[number]; type InputType = TextType | CheckType; type PromptOptions = { input: InputType; placeholder: string; entries: { value: string; text: string }[]; };
原写法使用条件类型,但TypeScript始终推断返回类型为string | string[],无法精准匹配:
type ReturnType<T extends InputType> = T extends TextType ? string : string[]; function foo(name: string, options: PromptOptions) { const value: ReturnType<typeof options.input>; }
解决方案
核心问题在于原函数没有通过泛型绑定options.input的具体类型,导致TypeScript只能识别到联合类型而非具体分支。以下两种修改方式均可解决问题:
方案1:将函数改为泛型函数
让泛型参数绑定options.input的具体类型,让TypeScript追踪到精准的类型分支:
type ReturnType<T extends InputType> = T extends TextType ? string : string[]; function foo<T extends InputType>(name: string, options: PromptOptions & { input: T }) { // 根据input类型编写业务逻辑,示例赋值仅做类型匹配 const value: ReturnType<T> = (options.input extends TextType ? "" : []) as ReturnType<T>; return value; }
方案2:将PromptOptions定义为泛型类型
更优雅的方式是直接让PromptOptions携带泛型参数,明确绑定input的类型:
// 修改PromptOptions为泛型类型 type PromptOptions<T extends InputType = InputType> = { input: T; placeholder: string; entries: { value: string; text: string }[]; }; type ReturnType<T extends InputType> = T extends TextType ? string : string[]; function foo<T extends InputType>(name: string, options: PromptOptions<T>) { // 根据input类型编写业务逻辑,示例赋值仅做类型匹配 const value: ReturnType<T> = (options.input extends TextType ? "default text" : ["default option"]) as ReturnType<T>; return value; }
效果验证
调用函数时,TypeScript会根据传入的input类型自动推断返回值类型:
// 返回值类型为string const textResult = foo("username", { input: "text", placeholder: "Enter your name", entries: [] }); // 返回值类型为string[] const checkResult = foo("hobbies", { input: "checkbox", placeholder: "Select hobbies", entries: [{ value: "reading", text: "Reading" }] });
内容的提问来源于stack exchange,提问作者Anton Ödman
相关产品推荐
相关产品推荐

