如何从TypeScript联合类型Entry派生保持属性关联的EntryInput?
问题描述
现有如下TypeScript联合类型:
type Entry = | {id: 'A', format: 'foo' | 'bar', value: 1 | 2} | {id: 'B', format: 'baz', value: 3 | 4} | {id: 'C', format: 'qux', value: 'hello' | 'goodbye'};
该类型的每个对象内部属性保持关联,比如id为'A'时,format只能是'foo'或'bar'。
需要从Entry派生出EntryInput类型:保留id属性,将format设为可选,移除value属性(作为函数输入参数,用于生成Entry类型实例)。但直接使用Pick或Omit等工具类型处理联合类型时,会导致所有属性混合,失去原有的属性关联。
解决方案
利用TypeScript的分布式条件类型,可以对联合类型的每个成员单独处理,从而在派生类型时保留原有的属性关联:
type EntryInput = Entry extends infer E ? Omit<E, 'value'> & { format?: E['format'] } : never;
类型说明
- 分布式条件类型会自动将
Entry联合类型拆分为单个成员,依次代入E进行处理 - 对每个成员
E,先用Omit<E, 'value'>移除value属性,再通过& { format?: E['format'] }将format设为可选,且保留该成员原有的format类型约束 - 最终结果会重新合并为联合类型,每个成员的
id与可选format的关联关系完全继承自原Entry类型
验证示例
合法的EntryInput实例:
const inputA: EntryInput = { id: 'A' }; // 合法,format可选 const inputAWithFormat: EntryInput = { id: 'A', format: 'foo' }; // 合法,format符合'A'的约束 const inputB: EntryInput = { id: 'B', format: 'baz' }; // 合法
非法实例会被TypeScript拦截:
const invalidInput: EntryInput = { id: 'A', format: 'baz' }; // 类型错误,'A'对应的format只能是'foo'|'bar'|undefined
配套函数示例
可以基于EntryInput编写类型安全的创建函数:
function createEntry(input: EntryInput): Entry { switch(input.id) { case 'A': return { ...input, value: 1 } as const; case 'B': return { ...input, value: 3 } as const; case 'C': return { ...input, value: 'hello' } as const; } }
内容的提问来源于stack exchange,提问作者JHH
相关产品推荐
相关产品推荐

