【问题标题】:How to type an object with generic keys of different types in typescript如何在打字稿中使用不同类型的通用键键入对象
【发布时间】:2022-04-08 01:30:58
【问题描述】:

你会如何在 typescript 中输入这些对象?

我有一个特殊的“日期时间”键,它是日期,其余键是数字。但我事先并不知道每个对象会设置哪些键。示例值:

type Metrics = ??????

const example1: Metrics = {
  datetime: new Date(),
  activity: 12.34,
  min: 12.34,
  max: 12.34,
}
const example2: Metrics = {
  datetime: new Date(),
  avg: 12.34,
}

这是我尝试过的:

type Metrics = {
  datetime: Date,
  [key: string]: number,
}
// ERROR on the type definition:
// Property 'datetime' of type 'Date' is not assignable to string index type 'number'


type Metrics = { 
    datetime: Date 
} & {  
    [key: string]: number 
}
// ERROR on the variable assignment:
// Type '{ datetime: Date; activity: number; min: number; max: number; }' is not assignable to type 'Metrics'.
//   Type '{ datetime: Date; activity: number; min: number; max: number; }' is not assignable to type '{ [key: string]: number | null; }'.
//     Property 'datetime' is incompatible with index signature.
//       Type 'Date' is not assignable to type 'number'.

【问题讨论】:

  • 您可以控制这些数据的格式吗?因为如果您将数字数据嵌套在其自己的对象中,其中 all 键都是数字,那么您的生活会轻松很多。 { datetime: Date, data: { [key: string]: number }
  • 如果您为所有属性定义键,那么“日期时间”也需要完全匹配:{ [key: string]: number | Date, datetime: Date }
  • @AlexWayne 事实上我是这样做的,这就是目前正在实施的,但我希望有一个解决方案来简化我的数据格式。
  • @fard 是的,这就是我观察到的。但是我的指标键不能是日期,这种类型现在对于指标键是错误的。另外,我不能提前指定属性键,因为它们是从数据库中提取的
  • @ClémentPrévost 如果您可以指定所有属性:typescriptlang.org/play?#code/…

标签: typescript typescript-typings


【解决方案1】:

您将需要使用Record<Exclude<K,"datetime">, number> 将所有现有键映射到类型数字但排除键“日期时间”的东西。由于通常的索引类型不一定可以做到这一点,因此您最好使用将类型限制为泛型的辅助函数:

type Metrics<K extends keyof any> = { datetime: Date } & Record<Exclude<K, "datetime">, number>;

function makeMetrics<T extends Metrics<keyof T>>(metrics: T): T {
    return metrics;
}

const example1 = makeMetrics({
    datetime: new Date(),
    activity: 12.34,
    min: 12.34,
    max: 12.34,
});
const example2 = makeMetrics({
    datetime: new Date(),
    avg: 12.34,
});

这意味着这两个示例将只允许在定义时存在的键,稍后添加额外的键则不会,以允许您需要“除datetime 之外的所有键都是数字”之类的东西据我所知是不可能的。

【讨论】:

    【解决方案2】:

    这有点笨拙,但我找到了一种方法来添加基于您的对象的类型。这允许您导出类型化的对象。

    1. 定义没有类型的对象
    const example1 = {
      datetime: new Date(),
      activity: 12.34,
      min: 12.34,
      max: 12.34,
    }
    
    1. 从该对象创建一个类型,但排除您要更改的特定键
    type AllKeys<T> = {
      [Property in keyof T]: number;
    };
    
    1. 使用 2 中的类型创建交集类型并省略您的日期时间键。请注意,“typeof example1”为您提供了 example1 中的所有键。
    type NewType = AllKeys<Omit<typeof example1, "datetime">> & { datetime: Date};
    
    1. 导出类型化对象
    export const example: NewType = example1;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-08
      • 2020-01-17
      • 2021-12-17
      • 2022-01-05
      • 2020-03-03
      • 1970-01-01
      • 2019-01-02
      • 2021-03-04
      相关资源
      最近更新 更多