flatten接受任何数据类型的数组,并生成每个嵌套数组展平的数组。
例如,[{}, 'hello', 2, [3, ['ay'], 'oi oi']变为[{}, 'hello', 2, 3, 'ay', 'oi oi'],[[[[5]]]]变为[5]。
我需要一个接口来描述这样的功能。我开始写它的时候认为它会很简单,但后来我坚持描述一个包含任何东西的数组,而不是其他数组。
interface Flatten {
(any[]): ...?
}欢迎有任何想法,谢谢:))
发布于 2021-09-10 07:46:26
它在TS4.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)您还应该向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])
}发布于 2021-09-10 07:24:09
如果你知道平面数组应该返回的所有数据类型,你可以这样定义它:
type Flat = string|number|FlatObj;
type FlatArr = Array<Flat>;
type FlatObj = {[key: string]: Flat|FlatArr};在您的示例中,您有嵌套的空对象,所以我假设您也希望它只包含平面数组,FlatObj是它的定义。
现在,如果您尝试在任何FlatArr变量中分配嵌套数组,它应该会报错。
链接到playground
如果您正在寻找类型保护,这里有一个适用于FlatArr和FlatObj的示例
type AnyObj = {[key: string]: any};
function isFlatObj(obj: AnyObj): obj is FlatObj {
let flat = true;
for (const key in obj) {
if (Array.isArray(obj[key]) && !isFlatArr(obj[key])) flat = false;
else if (typeof obj[key] === 'object' && !isFlatObj(obj[key])) flat = false;
}
return flat;
}
function isFlatArr(arr: any[]): arr is FlatArr {
let flat = true;
arr.map((item) => {
if (Array.isArray(item)) flat = false;
else if (typeof item === 'object' && !isFlatObj(item)) flat = false;
});
return flat;
}要制作FlatArr,您可以为它定义一个函数。我在下面做了两个函数。一个是使数组扁平,另一个是确保对象数组也是扁平的:
const flattenArr = (arr: any[]): FlatArr => {
const flatArr: FlatArr = [];
for (const item of arr) {
if (Array.isArray(item)) flatArr.push(...flattenArr(item));
else if (typeof item === 'string') flatArr.push(item);
else if (typeof item === 'number') flatArr.push(item);
else if (typeof item === 'object') flatArr.push(flattenObj(item));
}
return flatArr;
}
const flattenObj = (obj: AnyObj): FlatObj => {
let flatObj: FlatObj = {};
for (const key in obj) {
if (Array.isArray(obj[key])) flatObj[key] = flattenArr(obj[key]);
else if (typeof obj[key] === 'string') flatObj[key] = obj[key];
else if (typeof obj[key] === 'number') flatObj[key] = obj[key];
else if (typeof obj[key] === 'object') flatObj[key] = flattenObj(obj[key]);
}
return flatObj;
}https://stackoverflow.com/questions/69127304
复制相似问题