繁体   English   中英

如何在TypeScript中使用不同类型的项和特定顺序定义数组类型?

[英]How to define an array type with items of different types and with a specific order in TypeScript?

假设我想拥有一个数组,该数组的项目可以接受不同的类型,但还需要针对这些类型的特定顺序。

例如,假设MyArrayType要求第一个项目必须是A类型,最后一个项目必须是C类型,而介于两者之间的所有项目都必须是B类型。

const a: A = ....;
const b1: B = ....;
const b2: B = ....;
.
.
.
const bn: B = ....;
const c: C = ....;
const arr: MyArrayType = [a, b1, b2,...., bn, c]; //compiles
const arr2: MyArrayType = [c, b1, b2,...., bn, a]; //doesn't compile

可以定义这样的数组类型吗?

我想我明白了。 通过递归,我们可以在末尾创建C类型的元组,并在开始时创建B项对。

之后,按照建议@ titian-cernicova-dragomir,我们可以在元组的开头添加A类型。

不幸的是,此解决方案需要B项的准确计数。

码:

type A = 1;
type B = 2;
type C = 3;

type ZeroTuple = [];

type PrependTuple<A, T> = T extends Array<any>
  ? (((a: A, ...b: T) => void) extends (...a: infer I) => void ? I : [])
  : [];

type TupleLength<T extends Array<any>> = T["length"];

type NumberToTuple<N extends number, L extends Array<any> = [C]> = {
  true: L;
  false: NumberToTuple<N, PrependTuple<B, L>>;
}[TupleLength<L> extends N ? "true" : "false"];

type MyArrayType = PrependTuple<A, NumberToTuple<4>>;

// or make it more generic
type MyArrayType<N extends number> = PrependTuple<A, NumberToTuple<N>>;

NumberToTuple将以递归方式将B元素附加到[C],然后是[B,C],[B,B,C]。

在N次元组[... b [],C]之后,我们必须在A项之前添加。

我同意评论者的意见。 这种数据结构很难处理。 除了已经建议的以外,我还可以推荐类似[A, B[], C]

type ABC = [A, B[], C];

const arr: ABC = [a, [b1, b2, ...bn], c]; //compiles
const arr2: ABC = [c, [b1, b2, ...bn], a]; // does not compile

语法几乎与您所要求的相同,但是我知道这可能还不够。 如果潜在b的数量相对较少,您还可以执行以下操作:

type AB1C = [A, B, C];
type AB2C = [A, B, B, C];
type AB3C = [A, B, B, B, C];
type ABC = AB1C | AB2C | AB3C;

const arr: ABC = [a, b1, b2, bn, c]; //compiles
const arr2: ABC = [c, b1, b2, bn, a]; // does not compile

当然,它不是很优雅,但是请注意, length属性用作区分符,因此以下内容完全有效:

function getC(abc: ABC): C {
  switch (abc.length) {
    case 3: return abc[2];
    case 4: return abc[3];
    case 5: return abc[4];
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM