我有一个工具来创建一个静态大小的数组:

export type StaticArray<T, L extends number, R extends any[] = []> = R extends {
  length: L;
}
  ? R
  : StaticArray<T, L, [...R, T]>;

我可以验证它的工作:

let myVar: StaticArray<number, 3>;
//  ^? let myVar: [number, number, number]

然而,我想让它与sum类型一起工作,但我不确定它如何可能.我希望这个案子能有这样的结果:

let myVar: StaticArray<number, 3 | 2 | 1>;
//  ^? let myVar: [number, number, number] | [number, number] | [number]

但我似乎不工作,因为我的StaticArray类型停止在它看到的最小数字.

推荐答案

你是说你想要StaticArray<T, L>distributeunionsL,所以StaticArray<T, L1 | L2>等于StaticArray<T, L1> | StaticArray<T, L2>.

一般的方法是使用distributive conditional type. 当你写一个T extends U ? V : W形式的条件类型,其中T是一个generic类型参数,TypeScript会自动分布在T中的联合体上. 如果你只想把一个非分布类型转换成分布类型,你可以用一个"no-op"分布条件类型来包装它,比如T extends any ? ⋯ : never.这看起来像什么都没做(T总是延伸any),但它有分配给unions 的效果.

所以这就 bootstrap 我们写下

type StaticArray<T, L extends number, R extends any[] = []> =
  L extends any ? R extends { length: L; } ? R : StaticArray<T, L, [...R, T]> : never;

你可以看到它是按需要工作的

let myVar: StaticArray<number, 3>;
//  ^? let myVar: [number, number, number]

let myVar2: StaticArray<number, 3 | 2 | 1>;
//  ^? let myVar2: [number] | [number, number] | [number, number, number]

注意,T extends any ? ⋯ : never中的any可以替换为任何你确定T会扩展它的值.你可以使用unknown,或T,或一些约束(如number代替L),这取决于你的偏好.

Playground link to code

Typescript相关问答推荐

处理API响应中的日期对象

TS不推断类型在条件判断后具有属性'

在将对象从一个对象转换成另一个对象时,可以缩小对象的键吗?

如何判断输入是否是TypeScript中的品牌类型?

类型脚本满足将布尔类型转换为文字.这正常吗?

分解对象时出现打字错误

CDK从可选的Lambda角色属性承担角色/复合主体中没有非空断言

在列表的指令中使用intersectionObservable隐藏按钮

如何将别名添加到vitest配置文件?

是否有可能避免此泛型函数体中的类型断言?

类型';字符串|数字';不可分配给类型';未定义';.类型';字符串';不可分配给类型';未定义';

基于泛型的条件接口键

在Cypress中,您能找到表格中具有特定文本的第一行吗?

作为函数参数的联合类型的键

错误TS7030:并非所有代码路径都返回值.";由tsfig.json中的";Strong";:False引起

TypeScript:如何使用泛型和子类型创建泛型默认函数?

如何提取具有索引签名的类型中定义的键

是否使用类型将方法动态添加到类?

在 next.js 13.4 中为react-email-editor使用forwardRef和next/dynamic的正确方法

Mongodb TypeError:类继承 events_1.EventEmitter 不是对象或 null