【问题标题】:Define a type for an object where all values have the same type为所有值都具有相同类型的对象定义类型
【发布时间】:2020-06-10 12:35:37
【问题描述】:

我正在尝试为对象定义一个类型,这样对象的每个值都具有相同的类型,并且必须具有相同的键。我希望能够做到这一点,其中每个值都有相同的键,定义为所有值的类型的联合。

const test = {
  a: {               // I'd like to see a type error on this line
    x: 1,
  },
  b: {
    x: 1,
    y: 2,
  },
}

提前定义好类型是可以的:

interface IA {
  [key: string]: {
    x: number;
    y: number;
  }
}

const test: IA = {
  a: {         // now we get a type error because we don't have y on this object
    x: 1,
  },
  b: {
    x: 1,
    y: 2,
  },
};

我可以用这样的代码得到一些接近的东西:

const test = <T>(x: { [key: string]: { [key in keyof T]: string } }) => true;

另外,我们可以在函数中推断类型,但问题是它不采用所有类型的联合,而只采用对象中的第一个:

const test = <T>(x: { [key: string]: { [key in keyof T]: number } }) => true;

const x = test({
  a: {
    x: 1,
  },
  b: {
    x: 1,
    y: 2,            // now we get a type error here
  },
})

这里的类型错误是:

键入'{ x:数字; y:数字; }' 不可分配给类型 '{ x: 数字; }'。对象字面量只能指定已知属性,并且 'y' 不存在于类型 '{ x: number; }'。

我真的不明白如何在 typescript 中做到这一点,我怀疑这是不可能的 - 有人有什么建议吗?

【问题讨论】:

  • 第二个代码示例有什么问题?这不是你要找的吗?
  • 您希望错误转移到键数较少的属性上,而不是键数较多的属性上?这可能足够接近:typescriptlang.org/play/…
  • 亲爱的@MikeS,如果属性是动态创建的,您无法提前创建列表,因为您还不知道它们。每个属性 (a,b,..) 都应具有相同的编号、名称和相同类型的元素。这是一个非常复杂的用例:假设用户对一种语言进行了额外的更改而忘记更新其他语言。应该会自动识别。
  • @MikeS。抱歉,如果不清楚;我想要a 的值的错误,因为它的值不是所有值的联合类型。 b 上的值 的联合类型的所有值,所以应该没有错误
  • 亲爱的@TitianCernicova-Dragomir 我认为这是正确的答案,也是一个很好的答案,你会在这里添加它吗?非常感谢!

标签: typescript types rules type-definition


【解决方案1】:

这是来自@TitianCernicova-Dragomir 的一个很好的回答,here

type UnionKeys<U> = U extends U ? keyof U : never;

const test = <T>(x: T & Record<keyof T, Record<UnionKeys<T[keyof T]>, number>>) => true;

const x = test({
  a: {
    x: 1,
  },
  b: {
    x: 1,
    y: 2,
  },
})

【讨论】:

  • 这不是检查属性名称,但它很有帮助,..
猜你喜欢
  • 2017-05-27
  • 1970-01-01
  • 2012-04-19
  • 2018-03-20
  • 2017-09-03
  • 2021-09-07
  • 1970-01-01
  • 2022-01-25
  • 1970-01-01
相关资源
最近更新 更多