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

如何在TypeScript中构建带泛型的组合判别联合类型函数?

解决方案:基于联合类型的多层判别约束实现

1. 先定义基础类型映射

先把action、输入输出格式对应的类型规则统一定义,让TS能明确关联各属性的依赖关系:

// 定义支持的格式类型
type Format = 'json' | 'yaml' | 'csv';

// 映射格式对应的数据类型
type FormatData<T extends Format> = 
  T extends 'json' ? Record<string, any> :
  T extends 'yaml' ? string :
  T extends 'csv' ? string[][] :
  never;

// 枚举所有合法的Action参数组合(核心:用联合类型明确每个action的完整参数结构)
type ActionConfig = 
  | {
      action: 'convert';
      input: { format: Format };
      output: { format: Format };
      data: FormatData<this['input']['format']>;
    }
  | {
      action: 'format';
      input: { format: Format };
      output?: never; // format动作不需要output字段
      data: FormatData<this['input']['format']>;
    };

2. 实现call函数的类型约束与返回值推断

基于上面的联合类型,让call函数的入参和返回值做精准映射:

// 定义返回类型推断逻辑
type CallReturnType<T extends ActionConfig> = 
  T extends { action: 'convert' } 
    ? FormatData<T['output']['format']>
    : T extends { action: 'format' }
      ? FormatData<T['input']['format']>
      : never;

// 实现call函数
function call<T extends ActionConfig>(params: T): CallReturnType<T> {
  switch (params.action) {
    case 'convert':
      // 直接复用已实现的convert函数,类型已自动关联
      return convert(params.data, params.input.format, params.output.format) as CallReturnType<T>;
    case 'format':
      // 复用已实现的format函数
      return format(params.data, params.input.format) as CallReturnType<T>;
    default:
      throw new Error(`Unsupported action: ${(params as any).action}`);
  }
}

3. 扩展40+种Action的方式

新增action只需要在ActionConfig里追加新的联合成员,同步更新返回类型推断即可:

// 新增validate动作
type ActionConfig = 
  // 原有convert、format...
  | {
      action: 'validate';
      input: { format: Format; schema: Record<string, any> };
      output?: never;
      data: FormatData<this['input']['format']>;
    };

// 更新返回类型推断
type CallReturnType<T extends ActionConfig> = 
  // 原有判断逻辑...
  | T extends { action: 'validate' } ? boolean : never;

// 在call函数中新增处理分支
case 'validate':
  return validate(params.data, params.input.format, params.input.schema) as CallReturnType<T>;

4. 类型校验与推断效果示例

调用时TS会自动校验参数合法性,并精准推断返回类型:

// 合法调用:convert动作,输入json→输出yaml
const yamlResult = call({
  action: 'convert',
  input: { format: 'json' },
  output: { format: 'yaml' },
  data: { name: 'test' }
});
// yamlResult类型自动推断为string(对应yaml格式的类型)

// 错误调用:convert动作的data类型与input.format不匹配
call({
  action: 'convert',
  input: { format: 'csv' },
  output: { format: 'json' },
  data: { name: 'test' } // TS直接报错:类型不匹配csv要求的string[][]
});

原实现出错原因

之前的问题核心是没有用完整的联合类型枚举所有合法参数组合,而是试图用分散的类型条件约束,导致TS无法关联action、input.format、output.format等多属性的依赖关系。用联合类型明确每个action的完整参数结构后,TS就能正确执行判别式类型推断。


内容的提问来源于stack exchange,提问作者Lance Pollard

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 10:52:15