技术上是可以做到的。
考虑这个例子:
type key = "a" | "b" | "c"
type value = 1 | 2 | 3
// credits goes to https://stackoverflow.com/a/50375286
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 https://stackoverflow.com/questions/53953814/typescript-check-if-a-type-is-a-union#comment-94748994
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
我已将 key 和 value 都转换为元组,然后将它们合并。
但是,您不应在生产代码中执行此操作。这是不安全。
请看这个issue/17944 和我的question。
您永远不应该依赖联合订单以及Object.keys 订单。