summaryrefslogtreecommitdiffstats
path: root/dom/webgpu/tests/cts/checkout/src/common/util/types.ts
blob: dfd5e4b5eab5c6d73f555882daf471cc84a76600 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/** Forces a type to resolve its type definitions, to make it readable/debuggable. */
export type ResolveType<T> = T extends object
  ? T extends infer O
    ? { [K in keyof O]: ResolveType<O[K]> }
    : never
  : T;

/** Returns the type `true` iff X and Y are exactly equal */
export type TypeEqual<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2
  ? true
  : false;

/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
export function assertTypeTrue<T extends true>() {}

/**
 * Computes the intersection of a set of types, given the union of those types.
 *
 * From: https://stackoverflow.com/a/56375136
 */
export type UnionToIntersection<U> =
  /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
  (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;

/** "Type asserts" that `X` is a subtype of `Y`. */
type EnsureSubtype<X, Y> = X extends Y ? X : never;

type TupleHeadOr<T, Default> = T extends readonly [infer H, ...(readonly unknown[])] ? H : Default;
type TupleTailOr<T, Default> = T extends readonly [unknown, ...infer Tail] ? Tail : Default;
type TypeOr<T, Default> = T extends undefined ? Default : T;

/**
 * Zips a key tuple type and a value tuple type together into an object.
 *
 * @template Keys Keys of the resulting object.
 * @template Values Values of the resulting object. If a key corresponds to a `Values` member that
 *   is undefined or past the end, it defaults to the corresponding `Defaults` member.
 * @template Defaults Default values. If a key corresponds to a `Defaults` member that is past the
 *   end, the default falls back to `undefined`.
 */
export type ZipKeysWithValues<
  Keys extends readonly string[],
  Values extends readonly unknown[],
  Defaults extends readonly unknown[]
> =
  //
  Keys extends readonly [infer KHead, ...infer KTail]
    ? {
        readonly [k in EnsureSubtype<KHead, string>]: TypeOr<
          TupleHeadOr<Values, undefined>,
          TupleHeadOr<Defaults, undefined>
        >;
      } &
        ZipKeysWithValues<
          EnsureSubtype<KTail, readonly string[]>,
          TupleTailOr<Values, []>,
          TupleTailOr<Defaults, []>
        >
    : {}; // K exhausted