0

I search method for convert object type, for example

type a = {
   code: 404,
   hello: 'world'
};

to entries type that have format of tuple

type TypeA = [['code', 404], ['hello', 'world']];
// or
type TypeA = [['hello', 'world'], ['code', 404],];

but still can write only generic that will combine entries elements type in union

type Entries<T> = { [K in keyof T]: [K, T[K]] }[keyof T][];
// it's will generate
type wrongTypeA = (["code", 404] | ["hello", "world"])[]; // it is union
HardCoreQual
  • 331
  • 1
  • 3
  • 11
  • Have you tried using `Object.entries`? In this case, it will return `[string, 404 | "world"][]`. – Nick McCurdy Aug 06 '22 at 23:42
  • This is something you probably don't want to do. The order of properties inside of a `type` is not something that can be observed by the type system. To the compiler, the two types `type a = { b: 0, c: 0 }` and `type b = { c: 0, b: 0 }` are identical. There are ways to achieve this, but you should not expect them to work consistently as the compiler might throw around the order of properties in types unexpectedly. – Tobias S. Aug 07 '22 at 00:01
  • yes I don't expect that order will saved, all that I want is that result array will have one element of type code,404 and other hello,world , order can be any, main here is to avoid result of type union[] – HardCoreQual Aug 07 '22 at 00:04

1 Answers1

1

I hope I have warned you enough about why this is not a good idea. For a detailed explanation why this is a bad idea, see the first answer of this post. But either way, we can use the TuplifyUnion type from the answer to construct our type.

type UnionToIntersection<U> =
  (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never
type LastOf<T> =
  UnionToIntersection<T extends any ? () => T : never> extends () => (infer R) ? R : never

// TS4.0+
type Push<T extends any[], V> = [...T, V];

// TS4.1+
type TuplifyUnion<T, L = LastOf<T>, N = [T] extends [never] ? true : false> =
  true extends N ? [] : Push<TuplifyUnion<Exclude<T, L>>, L>

type Entries<T> = TuplifyUnion<keyof T> extends infer U 
  ? {
      [K in keyof U]: [U[K], T[U[K] & keyof T]]
    }
  : never

Here is the result.

type A = {
   code: 404,
   hello: 'world'
};

type TypeA = Entries<A>
//   ^? type TypeA = [["code", 404], ["hello", "world"]]

Playground

Tobias S.
  • 21,159
  • 4
  • 27
  • 45