它在 TS 4.5(夜间版本)中是可行的,但不是您所期望的。
感谢variadic-tuple-types,您可以这样做:
type Reducer<
Arr extends Array<unknown>,
Result extends Array<unknown> = []
> =
(Arr extends []
? Result
: (Arr extends [infer H, ...infer Tail]
? (H extends Array<any>
? Reducer<[...H, ...Tail], Result> : Reducer<Tail, [...Result, H]>) : never
)
)
// [1,2,3]
type Result = Reducer<[[[1], [[[[[[[2]]]]]]]], 3]>
// [1, 2, 3, 4, 5, 6]
type Result2 = Reducer<[[[[[[[[[1]]]]]]]],[[[[[[2,3,4]]]],[[[[5,6]]]]]]]>
如何将其用作函数返回值类型?
为了将它与函数一起使用,您需要将参数转换为不可变数组:
type Reducer<
Arr,
Result extends ReadonlyArray<unknown> = []
> = Arr extends ReadonlyArray<unknown> ?
(Arr extends readonly []
? Result
: (Arr extends readonly [infer H, ...infer Tail]
? (H extends ReadonlyArray<any>
? Reducer<readonly [...H, ...Tail], Result> : Reducer<Tail, readonly [...Result, H]>) : never
)
) : never
const flatten = <
Elem,
T extends ReadonlyArray<T | Elem>
>(arr: readonly [...T]): Reducer<T> =>
arr.reduce((acc, elem) =>
Array.isArray(elem)
? flatten(elem) as Reducer<T>
: [...acc, elem] as Reducer<T>,
[] as Reducer<T>
)
const result = flatten([[[[[[1]]], 2], 3]] as const)
Playground
您还应该向reduce 方法添加第二个参数。
更多解释你可以在我的article找到。
如果您想更好地了解 Reducer 实用程序类型的工作原理,请参阅此示例:
const Reducer = <T,>(Arr: ReadonlyArray<T>, Result: ReadonlyArray<T> = [])
: ReadonlyArray<T> => {
if (Arr.length === 0) {
return Result
}
const [Head, ...Tail] = Arr;
if (Array.isArray(Head)) {
return Reducer([...Head, ...Tail], Result)
}
return Reducer(Tail, [...Result, Head])
}