首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >除其他数组外的任何数组的Typescript接口

除其他数组外的任何数组的Typescript接口
EN

Stack Overflow用户
提问于 2021-09-10 04:33:02
回答 2查看 183关注 0票数 4

flatten接受任何数据类型的数组,并生成每个嵌套数组展平的数组。

例如,[{}, 'hello', 2, [3, ['ay'], 'oi oi']变为[{}, 'hello', 2, 3, 'ay', 'oi oi'][[[[5]]]]变为[5]

我需要一个接口来描述这样的功能。我开始写它的时候认为它会很简单,但后来我坚持描述一个包含任何东西的数组,而不是其他数组。

代码语言:javascript
复制
interface Flatten {
  (any[]): ...?
}

欢迎有任何想法,谢谢:))

EN

回答 2

Stack Overflow用户

发布于 2021-09-10 07:46:26

它在TS4.5(夜间版)中是可行的,但不是以你所期望的方式。

多亏了variadic-tuple-types,你可以做到这一点:

代码语言:javascript
复制
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]]]]]]]> 

如何将其用作函数返回值类型?

为了在函数中使用它,你需要将参数转换成不可变的数组:

代码语言:javascript
复制
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实用程序类型是如何工作的,请参阅以下示例:

代码语言:javascript
复制
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])
}
票数 2
EN

Stack Overflow用户

发布于 2021-09-10 07:24:09

如果你知道平面数组应该返回的所有数据类型,你可以这样定义它:

代码语言:javascript
复制
type Flat = string|number|FlatObj;
type FlatArr = Array<Flat>;
type FlatObj = {[key: string]: Flat|FlatArr};

在您的示例中,您有嵌套的空对象,所以我假设您也希望它只包含平面数组,FlatObj是它的定义。

现在,如果您尝试在任何FlatArr变量中分配嵌套数组,它应该会报错。

链接到playground

如果您正在寻找类型保护,这里有一个适用于FlatArrFlatObj的示例

代码语言:javascript
复制
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,您可以为它定义一个函数。我在下面做了两个函数。一个是使数组扁平,另一个是确保对象数组也是扁平的:

代码语言:javascript
复制
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;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69127304

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档