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

TypeScript联合类型导致记录值提取异常的技术问询

TypeScript联合类型参数下的Type类型取值错误修复

问题背景

现有以下TypeScript类型定义,用于根据传入的配置记录All和可选参数Part提取各属性取值:若Part指定了对应key的值则取该值,否则取元组中的默认值。

type BuildPart<T extends Record<string, [string, string]>> = '' | {
    [K in keyof T]: K extends string ? `${K & string}:${T[K][number]}` : never
}[keyof T]

type Type<All extends Record<string, [string, string]>, Part extends BuildPart<All> = ''> = {
    [K in keyof All]: K extends string ? Part extends `${K}:${infer V}` ? V : All[K][1] : never
}[keyof All]

测试场景中,Part为空或单个值时功能正常,但Part为联合类型时结果不符合预期:

type test0 = Type<{a: ['b' | 'c', 'c'], b: ['d' | 'e', 'd']}>                   // 'c' | 'd'(符合预期)
type test1 = Type<{a: ['b' | 'c', 'c'], b: ['d' | 'e', 'd']}, 'a:b'>            // 'b' | 'd'(符合预期)
type test2 = Type<{a: ['b' | 'c', 'c'], b: ['d' | 'e', 'd']}, 'a:b' | 'b:e'>    // 实际得'b' | 'c' | 'd' | 'e',预期为'b' | 'e'

问题原因

原类型中的Part extends ${K}:${infer V}``属于分布式条件类型:当Part是联合类型时,TypeScript会自动遍历联合中的每个成员单独进行条件判断,再将结果合并。

以test2为例:

  • 针对K='a',Part的两个成员'a:b'和'b:e'会分别判断:'a:b'匹配规则得到V='b','b:e'不匹配则取默认值'c',最终K='a'的结果是'b' | 'c'。
  • 针对K='b',同理会得到'd' | 'e'。
  • 合并后出现所有可能值,与预期不符。

解决方案

避免分布式条件类型的影响,改为对整个Part联合判断是否存在当前K对应的条目。用Extract<Part, ${K}:${string}>提取Part中属于当前K的部分,再进行值推断。

修正后的类型定义:

type BuildPart<T extends Record<string, [string, string]>> = '' | {
    [K in keyof T]: K extends string ? `${K & string}:${T[K][number]}` : never
}[keyof T]

type Type<All extends Record<string, [string, string]>, Part extends BuildPart<All> = ''> = {
    [K in keyof All]: K extends string 
      ? Extract<Part, `${K}:${string}`> extends `${K}:${infer V}` 
        ? V 
        : All[K][1] 
      : never
}[keyof All]

测试验证

修正后重新测试,结果符合预期:

type test0 = Type<{a: ['b' | 'c', 'c'], b: ['d' | 'e', 'd']}>                   // 'c' | 'd'(符合预期)
type test1 = Type<{a: ['b' | 'c', 'c'], b: ['d' | 'e', 'd']}, 'a:b'>            // 'b' | 'd'(符合预期)
type test2 = Type<{a: ['b' | 'c', 'c'], b: ['d' | 'e', 'd']}, 'a:b' | 'b:e'>    // 'b' | 'e'(符合预期)

原理说明

  • Extract<Part, ${K}:${string}>会从Part联合中筛选出所有符合${K}:xxx格式的条目,若不存在则返回never。
  • 针对筛选结果推断:如果有匹配条目,就提取对应的V;否则取默认值。这样每个K只会得到指定值或默认值,不会产生多余的联合分支。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 01:47:30