打字稿从 2 个联合类型生成索引签名类型

typescript generate index signature type from 2 union types

给出

type key = "a" | "b" | "c"
type value = 1 | 2 | 3

我想使用上面的两个联合类型生成 {a:1, b:2, c:3}

type A<K,V> = ?????

什么是?????

从技术上讲,这是可以做到的。 考虑这个例子:

type key = "a" | "b" | "c"
type value = 1 | 2 | 3

// credits goes to 
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
  k: infer I
) => void
  ? I
  : never;

// credits goes to https://github.com/microsoft/TypeScript/issues/13298#issuecomment-468114901
type UnionToOvlds<U> = UnionToIntersection<
  U extends any ? (f: U) => void : never
>;

type PopUnion<U> = UnionToOvlds<U> extends (a: infer A) => void ? A : never;

// credits goes to 
type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true;

type UnionToArray<T, A extends unknown[] = []> = IsUnion<T> extends true
  ? UnionToArray<Exclude<T, PopUnion<T>>, [PopUnion<T>, ...A]>
  : [T, ...A];

type Length<T extends ReadonlyArray<any>> = T extends { length: infer L }
  ? L
  : never;

type CompareLength<
  X extends ReadonlyArray<any>,
  Y extends ReadonlyArray<any>
  > = Length<X> extends Length<Y> ? true : false;


type Callback<T, U> = T extends PropertyKey ? U extends PropertyKey ? Record<T, U> : never : never

// https://catchts.com/tuples#zip 
type Zip<
  T extends ReadonlyArray<any>,
  U extends ReadonlyArray<any>,
  Result extends Record<string, any> = {}> =
  (CompareLength<T, U> extends true
    ? (T extends []
      ? Result
      : (T extends [infer HeadT1]
        ? (U extends [infer HeadU1]
          ? Result & Callback<HeadT1, HeadU1>
          : never)
        : (T extends [infer HeadT2, ...infer TailT2]
          ? (U extends [infer HeadU2, ...infer TailU2]
            ? Zip<TailT2, TailU2, Result & Callback<HeadT2, HeadU2>>
            : never)
          : never
        )
      )
    )
    : never);



type Keys = UnionToArray<key>;

type Values = UnionToArray<value>

// Record<"a", 1> & Record<"b", 2> & Record<"c", 3>
type Result = Zip<Keys, Values>

Playground

我已将 keyvalue 都转换为元组,然后将它们合并。

但是,您不应在生产代码中执行此操作。 不安全。 请看这个 issue/17944 and my question.

你永远不应该像 Object.keys 那样依赖联合秩序。