You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript数组类型进阶问题:自定义索引取类型及相关疑问

问题解答

1. 实现索引超出数组长度时返回never类型

要实现该需求,需要在类型层面判断索引N是否处于数组的有效范围(0 ≤ N < T['length'])。可以通过递归生成有效索引范围,再判断N是否属于该范围来实现:

// 生成从0到N-1的数字字面量联合类型
type NumberLessThan<N extends number, Acc extends number[] = []> = 
  Acc['length'] extends N 
    ? Acc[number] 
    : NumberLessThan<N, [...Acc, Acc['length']]>;

// 改进后的El类型
type El<T extends unknown[], N extends number> = 
  N extends NumberLessThan<T['length']> 
    ? T[N] 
    : never;

// 测试用例
type Test1 = El<[1, '2', 4], 2>; // 4(有效索引)
type Test2 = El<[1, '2', 4], 3>; // never(超出长度)
type Test3 = El<[], 0>; // never(空数组)

也可以用更简洁的方式,利用TypeScript元组索引的特性——仅当N是元组的有效元素索引时,T[N]才返回对应类型,否则通过条件判断返回never:

type El<T extends unknown[], N extends number> = 
  T extends { [K in N]: infer U } 
    ? U 
    : never;

type Test4 = El<[1, '2', 4], 3>; // never

2. 为什么el2的类型是string | number而非number?

你定义的const arr = [1,'2',4]被TypeScript默认推断为数组类型(string | number)[],而非元组类型[1, '2', 4]。数组类型的所有元素都是联合类型,因此无论索引是多少,T[N]都会返回元素的联合类型string | number。

若要让TypeScript将其推断为元组,需要使用as const断言,强制保留字面量类型和元组结构:

const arr = [1,'2',4] as const; // 类型为readonly [1, "2", 4]
let el2: El<typeof arr, 2>; // 类型为4,符合预期

3. 为什么el3会报错?

类型参数T要求传入的是类型,而arr是一个值,并非类型。在TypeScript中,要获取值的类型必须使用typeof操作符,因此正确写法是El<typeof arr, 2>,而非直接传递arr作为类型参数。

内容的提问来源于stack exchange,提问作者alexandr2006

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 01:55:07