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

TypeScript:如何创建可推断的可选元组类型?

泛型元组类型默认值与类型兼容问题解决

需求与初始尝试

想要定义一个泛型元组类型IO,包含两个元素,未指定类型时默认值为void。第一次尝试的代码如下:

/** Initial attempt */
type IO<I = void, O = void> = [I, O];
/** resolves as `false` */
type Test = [string, number] extends IO ? true : false;

此时Test的结果是false,TypeScript认为[string, number]不兼容IO——因为直接使用IO时会自动填充默认的void类型,变成[void, void],自然无法匹配其他类型的元组。

替代方案的缺陷

把默认值换成any并将元组元素设为可选后,类型兼容问题得到解决:

/** Second attempt replacing `void` with `any` */
type IO<I = any, O = any> = [I?, O?];
type Test = [string, number] extends IO ? true : false;

这里Test的结果是true,但新的问题出现了:类型推断无法得到预期的void值。比如:

type InferI<Test extends IO<any, any>> = Test extends IO<infer I, any> ? I : never;
type InferO<Test extends IO<any, any>> = Test extends IO<any, infer O> ? O : never;
/** resolves as `unknown` instead of `void` */
type O = InferO<[string, number]>;

O的推断结果是unknown,而非预期的void,破坏了默认值的语义。

问题根源与最终解决

后来发现问题被复杂化了,最初的IO定义本身是可行的,问题出在接口继承的场景中:

interface IOConfig {
  [key: string]: IO;
}
interface Test extends IOConfig {
  test: [string, number];
}

这里IO没有传入泛型参数,TypeScript会默认使用[void, void]作为类型,导致[string, number]不兼容。

只需要将IOConfig中的类型改为IO<any, any>,就能让它接受任意符合结构的元组类型:

interface IOConfig {
  [key: string]: IO<any, any>;
}
interface Test extends IOConfig {
  test: [string, number];
}

这样既保留了IO默认值为void的特性,又解决了类型兼容问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 09:42:35