TypeScript中如何基于type字段约束MyInput的value联合类型?
TypeScript 联合类型类型推断问题解决
原定义接口
interface MyInput { id: string, label: string, setter: Function, type: string, value: string | string[] | boolean, options?: string[] }
遇到的错误
Property 'map' does not exist on type 'string | boolean | string[]'.
Type 'string | boolean | string[]' is not assignable to type 'boolean | undefined'.
解决方案
方案1:使用区分联合类型(Discriminated Union)
利用type字段作为区分标志,将原接口重构为多个子接口的联合类型,让TypeScript通过type自动推断value的具体类型:
type MyInput = // 文本输入:type为'text',value对应string类型 | { id: string; label: string; setter: Function; type: 'text'; value: string; options?: never } // 复选框:type为'checkbox',value对应boolean类型 | { id: string; label: string; setter: Function; type: 'checkbox'; value: boolean; options?: never } // 下拉选择:type为'select',value对应string[]类型,可带options | { id: string; label: string; setter: Function; type: 'select'; value: string[]; options?: string[] };
使用时,TypeScript会根据type字段自动窄化value的类型:
function renderInput(input: MyInput) { switch(input.type) { case 'text': // 此处input.value自动推断为string类型 console.log(input.value.toUpperCase()); break; case 'checkbox': // 此处input.value自动推断为boolean类型 const isChecked = input.value; break; case 'select': // 此处input.value自动推断为string[]类型,可安全调用map input.value.map(opt => `<option>${opt}</option>`); break; } }
方案2:类型守卫(Type Guards)
如果不想修改原接口结构,可在使用时通过类型守卫手动窄化value的类型:
内置类型守卫
利用typeof和Array.isArray做基础类型判断:
function handleInput(input: MyInput) { // 处理string[]类型的value if (Array.isArray(input.value)) { input.value.map(item => console.log(item)); // 无类型错误 } // 处理boolean类型的value if (typeof input.value === 'boolean') { const boolValue: boolean = input.value; // 类型匹配 } // 处理string类型的value if (typeof input.value === 'string') { const strValue: string = input.value; // 类型匹配 } }
自定义类型守卫
结合type字段做更精准的类型判断:
// 自定义类型守卫,判断是否为select类型输入 function isSelectInput(input: MyInput): input is MyInput & { value: string[] } { return input.type === 'select'; } // 使用示例 const input: MyInput = { /* ... */ }; if (isSelectInput(input)) { input.value.map(opt => console.log(opt)); // 安全调用map }
内容的提问来源于stack exchange,提问作者QuentinC
相关产品推荐
相关产品推荐

