首页 > 解决方案 > 如何从打字稿中另一种类型的成员中获取元组类型?

问题描述

假设我有这样的类型,有几个成员:

type TheType = {
    PK_1: number;
    PK_2: number;    // The type may same as other
    PK_3: boolean;
    PK_4: string;
}

我想得到一个类型的元组,其中包含上面每个成员的每种类型,例如:

// Should return as [number, number, boolean, string]
type TypeTuple = ToTuple<TheType>;  // How to make this ToTuple method?

标签: typescript

解决方案


type TheType = {
    PK_1: number;
    PK_2: number;    // The type may same as other
    PK_3: boolean;
    PK_4: string;
}

// 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;

// credit 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 MapPredicate<Obj, Key> = Key extends keyof Obj ? Obj[Key] : never

// credit goes to https://catchts.com/tuples#map
type Mapped<
    Obj,
    Arr extends Array<unknown>,
    Result extends Array<unknown> = [],
    > = Arr extends []
    ? []
    : Arr extends [infer H]
    ? [...Result, MapPredicate<Obj, H>]
    : Arr extends [infer Head, ...infer Tail]
    ? Mapped<Obj, [...Tail], [...Result, MapPredicate<Obj, Head>]>
    : Readonly<Result>;

type Result = Mapped<TheType, UnionToArray<keyof TheType>>; // [number, number, boolean, string]

操场

关于将联合转换为数组,您可以在此处找到更多解释

因为这个答案是现有解决方案的混合,您可以在我留在每个助手上方的适当链接中找到更多解释


推荐阅读