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

如何为多模型派生的列定义映射获取正确的TypeScript类型标注

问题根因

  • 使用交叉类型 User & Book & UserUID 时,三个模型中同名的 id 字段类型分别是 number、number、string,TypeScript 对交叉类型的同名字段会做类型交叉运算,number & string 的结果是 never,所以会出现 id 字段推导为 never 的问题。
  • 直接使用三个模型的联合类型时,keyof 联合类型 只能获取到所有模型共有的属性,因此除了所有模型都有的 id 字段外,其他字段都无法被识别。

解决思路

实现工具类型,把多个模型的所有字段汇总,同名字段的类型取所有模型中该字段类型的联合而非交叉:

  1. 把所有用到的模型汇总为一个联合类型
  2. 提取所有模型的所有字段名组成联合
  3. 对每个字段名,收集所有模型中该字段的类型组成联合
  4. 基于汇总后的类型定义列映射

完整可运行代码如下:

export type User = {
  id: number;
  admin: boolean;
  email: string;
};

export type Book = {
  id: number;
  title: string;
  author: string;
  userId: number;
};

export type UserUID = {
  id: string;
  admin: boolean;
  email: string;
};

// 汇总所有模型为联合类型
type AllModels = User | Book | UserUID;

// 工具类型:提取所有模型的所有字段名
type AllModelKeys<T> = T extends any ? keyof T : never;
// 工具类型:提取指定字段在所有模型中的类型联合
type GetFieldType<T, K extends PropertyKey> = T extends Record<K, infer V> ? V : never;
// 汇总后的字段类型:同名字段类型取联合
type MergedDataRow<T> = {
  [K in AllModelKeys<T>]: GetFieldType<T, K>
};

// 基于汇总类型定义列配置
export interface ColumnDefinition<F extends keyof MergedDataRow<AllModels>> {
  valueFormatter?: (value: MergedDataRow<AllModels>[F]) => string;
}

// 字段后加?表示允许只配置部分字段,需要强制全量配置可删除?
type ColumnDefinitionMap = {
  [key in keyof MergedDataRow<AllModels>]?: ColumnDefinition<key>;
};

const columnDefinitions: ColumnDefinitionMap = {
  admin: {
    // 类型正常推导为 boolean
    valueFormatter: (value) => (value === true ? 'Admin' : 'User'),
  },
  id: {
    // 类型正常推导为 number | string
    valueFormatter: (value) => typeof value === 'string' ? value : value.toString(),
  },
  // 其他非共有字段也可以正常识别
  title: {
    valueFormatter: (value) => `《${value}》`
  }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.20 05:15:07