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

如何基于Person类型创建仅允许指定name的判别联合类型?

正确实现基于Person的判别联合类型PersonPreferences

你之前用交叉类型的方式没触发错误,是因为Person和{name: 'jimmy', ...}交叉后,name的类型会变成('john'|'kate') & 'jimmy'(也就是never),但TypeScript不会对never类型的联合成员主动抛出错误,导致不符合要求的name被允许了。

下面是两种可靠的实现方式:

方法一:显式定义联合并通过工具类型约束

先封装一个工具类型确保每个联合成员都符合Person结构,再定义最终的联合类型,错误的name会直接触发类型报错:

type PersonNames = 'john' | 'kate';
type Person = {
  name: PersonNames;
  favorites: unknown;
};

// 工具类型:仅保留符合Person结构的类型,不符合的会被转为never
type EnsurePerson<T> = T extends Person ? T : never;

type PersonPreferences = EnsurePerson<
| {
    name: 'john';
    favorites: {
      food: 'pizza';
    };
  }
| {
    name: 'kate';
    favorites: {
      book: 'horror';
    };
  }
// | {
//     name: 'jimmy'; // 这里会直接报错:类型"{ name: 'jimmy'; favorites: { book: 'science'; }; }"不满足"Person"约束
//     favorites: {
//       book: 'science';
//     };
//   }
>;

方法二:利用映射类型自动生成联合

如果PersonNames的成员可能变动,这种方式扩展性更强,能自动根据PersonNames生成对应的联合类型,且强制name必须是PersonNames中的值:

type PersonNames = 'john' | 'kate';
type Person = {
  name: PersonNames;
  favorites: unknown;
};

// 定义每个name对应的专属favorites类型,键必须是PersonNames的子集
type PersonFavoritesMap = {
  john: { food: 'pizza' };
  kate: { book: 'horror' };
  // jimmy: { book: 'science' }; // 这里会报错:类型"jimmy"不满足"PersonNames"约束
};

// 自动生成PersonPreferences联合类型
type PersonPreferences = {
  [K in keyof PersonFavoritesMap]: {
    name: K;
    favorites: PersonFavoritesMap[K];
  };
}[keyof PersonFavoritesMap];

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 10:22:48