为所有值都具有相同类型的对象定义类型

问题描述 投票:2回答:1

我正在尝试为对象定义类型,以使对象的每个值都具有相同的类型,并且必须具有相同的键。我希望能够在每个值具有相同键(定义为所有值的类型的并集)的情况下执行此操作。

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 types rules type-definition
1个回答
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,
  },
})
© www.soinside.com 2019 - 2024. All rights reserved.