Define a type for an object where all values have the same type

寵の児 提交于 2020-06-26 12:09:34

问题


I'm trying to define a type for an object, such that every value of the object has the same type, and must have the same keys. I'd like to be able to do this where every value has the same keys, defined as the union of the types of all the values.

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

It's possible when you define the type in advance:

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

I can get something close with code like this:

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

Alternatively, in a function we can infer the type, but then the problem is that it doesn't take a union of all the types, but only the first in the object:

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
  },
})

The type error here is:

Type '{ x: number; y: number; }' is not assignable to type '{ x: number; }'. Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; }'.

I don't really see how this can be done in typescript, and I suspect it isn't possible - does anyone have any suggestions?


回答1:


That's a great answer from @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,
  },
})


来源:https://stackoverflow.com/questions/62303746/define-a-type-for-an-object-where-all-values-have-the-same-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!