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

TypeScript:为动态生成的类型添加额外属性

问题描述

现有以下TypeScript类型定义:

export enum Category {
  car = 'car',
  truck = 'truck',
}

export interface Property {
  readonly name: string,
  readonly label: string,
  readonly type: 'number' | 'string',
}

export interface CategoryDefinition {
  readonly category: Category,
  readonly label: string,
  readonly properties: readonly Property[]
}

type TypeMap = {
  string: string;
  number: number;
};

type FromDefinition<D extends CategoryDefinition> = {
  [T in D['properties'][number] as T['name']]: TypeMap[T['type']];
};

通过如下定义生成Car类型:

const car = {
      category: Category.car,
      label: 'Car',
      properties: [
      {
        name: 'weight',
        label: 'Weight',
        type: 'number',
      }
    ],
} as const satisfies CategoryDefinition; 

export type Car = FromDefinition<typeof car>;

当前生成的类型是:

type Car = {
    weight: number;
}

现在需要扩展FromDefinition类型,让生成的类型包含category属性,期望结果为:

type Car = {
    category: 'car';
    weight: number;
}

尝试过交叉类型的方式:

export type CategoryExtension= {
  category: Category
};

type FromDefinition<D extends CategoryDefinition> = {
  [T in D['properties'][number] as T['name']]: TypeMap[T['type']];
} & CategoryExtension;

但生成的类型显示不够直观,会以交叉类型的形式呈现:

type Car = {
    weight: number;
} & CategoryExtension

需要让生成的类型直接展开为包含category属性的对象类型,而非交叉类型形式。

解决方案

方案1:直接合并属性到映射类型

可以直接在FromDefinition中把category属性和映射出的属性合并,利用泛型参数D的具体类型推导category的精确类型:

type FromDefinition<D extends CategoryDefinition> = {
  category: D['category'];
} & {
  [T in D['properties'][number] as T['name']]: TypeMap[T['type']];
};

方案2:使用工具类型优化显示

如果编辑器仍然显示为交叉类型,可以借助Prettify工具类型强制展开为单一对象类型:

// 工具类型:展开交叉类型为单一对象
type Prettify<T> = {
  [K in keyof T]: T[K];
} & {};

type FromDefinition<D extends CategoryDefinition> = Prettify<{
  [T in D['properties'][number] as T['name']]: TypeMap[T['type']];
} & {
  category: D['category'];
}>;

最终生成的Car类型会显示为:

type Car = {
    category: 'car';
    weight: number;
}

注:由于你已经给car常量添加了as const断言,D['category']会被推导为枚举成员的字面量值,编辑器会自动显示为'car'而非Category.car。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 09:55:15