typescript 通过附加属性扩展动态生成的类型

at0kjp5o  于 2023-01-14  发布在  TypeScript
关注(0)|答案(1)|浏览(112)

基于这个问题,我实现了我的自定义类型:

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']];
};

为此(大致):

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;
}

比方说,我必须扩展这个类型,使它包含类别,如下所示:

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; // <----

export type Car = FromDefinition<typeof car>;

这就是我想要的结果,但看起来很奇怪:

type Car = {
    height: number;
} & CategoryExtension // <----

如何创建以下内容?:

type Car = {
    height: number;
    category: 'car' // or Category
}
fwzugrvs

fwzugrvs1#

传统上,这通过使TS推断结果和同态Map类型来完成:

type FromDefinition<D extends CategoryDefinition> = ({
  [T in D['properties'][number] as T['name']]: TypeMap[T['type']];
} & CategoryExtension) extends infer O ? { [K in keyof O]: O[K] } : never;
//                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

相关问题