You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 08:22:57