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

如何基于Record键值收窄TypeScript可辨识联合类型?

如何让Record类型根据可辨识联合的type键自动推断对应值的类型?

我有一个包含type可辨识属性的联合类型,现在要声明一个Record类型,键是联合类型中type属性的值。怎么声明Record的第二个泛型参数,让记录里的值能根据对应键自动推断出正确的类型?

interface Dog {
  type: 'dog';
  breed: string;
}

interface Vehicle {
  type: 'vehicle';
  max_speed: number;
};

type Thing = Dog | Vehicle;

const printMap: Record<Thing['type'], (thing: Thing) => string> = {
  'dog': x => `Dog ${x.breed}`,
                    // ^^^^^ 类型“Thing”上不存在属性“breed”。类型“Vehicle”上不存在属性“breed”。
                    // 怎么让TypeScript知道因为键是'dog',所以x是Dog类型?
  'vehicle': x => `Vehicle max speed ${x.max_speed}`
                                      // ^^^^^^^^^ 类型“Thing”上不存在属性“max_speed”。类型“Dog”上不存在属性“max_speed”。
                                      // 怎么让TypeScript知道因为键是'vehicle',所以x是Vehicle类型?
}

解决方案:用映射类型替代Record

Record的第二个泛型参数是统一的类型,没办法根据不同的键做差异化推断。你需要用映射类型来为每个type键关联对应的具体类型:

首先定义一个匹配可辨识联合的映射类型:

type ThingMap = {
  // 遍历Thing的所有type值作为键
  [T in Thing['type']]: 
    // 从Thing中提取type等于当前T的具体类型,作为函数参数
    (thing: Extract<Thing, { type: T }>) => string;
};

然后把printMap的类型改成ThingMap:

const printMap: ThingMap = {
  'dog': x => `Dog ${x.breed}`, // x自动推断为Dog类型,不再报错
  'vehicle': x => `Vehicle max speed ${x.max_speed}` // x自动推断为Vehicle类型,不再报错
};

通用化工具类型(可选)

如果需要复用这个逻辑,可以把它封装成通用工具类型:

// T是带type可辨识属性的联合类型,V是函数返回值类型(默认string)
type DiscriminatedRecord<T extends { type: string }, V = string> = {
  [K in T['type']]: (item: Extract<T, { type: K }>) => V;
};

// 使用时直接传入你的联合类型即可
const printMap: DiscriminatedRecord<Thing> = {
  'dog': x => `Dog ${x.breed}`,
  'vehicle': x => `Vehicle max speed ${x.max_speed}`
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 02:15:31