// 实现 ToFlatTuple
type IsTuple<T> = T extends
| readonly []
| readonly [any, ...any]
| readonly [...any, any]
? true
: false
type ToFlatTuple<T extends any[]> = IsTuple<T> extends true ? T extends [infer X, ...infer Y] ? X extends any[] ? [
...ToFlatTuple<X>,
...ToFlatTuple<Y>
] : [X, ...ToFlatTuple<Y>] : [] : never;
type CASE = ToFlatTuple<[1, 2, { a: 3 }]>;// [1, 2, { a: 3 }]
type CASE_1 = ToFlatTuple<[1, [{ a: 2, length: 2, c: [1] }], [3]]>; // [1, { a:2, length:2, c:[1] }, 3]
type CASE_2 = ToFlatTuple<[1,[2],3,[4,[5], [{ a: 6 }, [7]]]]>; // [1, 2, 3, 4, 5, {a:6}, 7]
type CASE_3 = ToFlatTuple<[number, [string]]>; // [number, string]
type CASE_4 = ToFlatTuple<[number[], [string]]>; // [...number[], string]
type CASE_5 = ToFlatTuple<number[]>; // never: number[] is not tuple
type CASE_6 = ToFlatTuple<number[][]>; // never: number[][] is not tuple
展开
Jack Q
2024-08-21来自广东
// 实现 Assign (类似js中Object.assign(A,B)效果,存在B与A存在相同属性时,B会覆盖A中对应的属性值)
type MergeArrayTarget<A,B> = {
[key in keyof B as key extends number ? key : never]: B[key]
} & {
[key in keyof A as key extends number ? never : key]: A[key]
}
type MergeTupleTarget<A,B> = {
[key in keyof B as key extends `${number}` ? key : never]: B[key]
} & {
[key in keyof A as key extends (`${number}` | number) ? never : key]: A[key]
};
type MergeTarget<T> = {
[K in keyof T]: T[K]
};
type NormalMerge<A,B> =
// A & B 共有属性
{
[key in Extract<keyof B, keyof A>]: B[key]
} &
// A 中去除 B 上相同的属性
{
[key in keyof A as key extends Extract<keyof B, keyof A> ? never : key]: A[key]
} &
// B 中去除 A 上相同的 string | number 类型属性
{
[key in Exclude<keyof B, keyof A> as key extends string | number ? key : never]: B[key]
}
type Assign<A, B> = AnyOrNever<A> extends true ? A : // current A is any or never
[A] extends [LiteralType] ? A : // current A IsLiteral :
[A] extends [object] ? // charge A is interface
AnyOrNever<B> extends true ? A :
[B] extends [LiteralType] ? A :
[B] extends [object] ? IsArray<B> extends true ? MergeTarget<MergeArrayTarget<A, B>> :
IsTuple<B> extends true ? MergeTarget<MergeTupleTarget<A, B>> :
MergeTarget<NormalMerge<A,B>>
: A
: ([A] extends [symbol] ?
symbol : // symbol will return it self
never); // void or undefined (throw error in js)