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

如何为多泛型参数类型的可变参数函数实现正确类型推断?

多泛型参数可变参数函数的类型推断解决方案

单泛型参数场景

首先定义单泛型类型:

type O1<T> = { a: T, b: NoInfer<T> };

接着声明两个不同的单参数泛型函数:

function f1T<T>(arg: O1<T>) {}
function f1O<T, G extends O1<T>>(arg: G) {}

调用时可见,f1T能正确校验类型,而f1O无法完成正确推断:

f1T/*<number>*/({ a: 0, b: ''}); // 报错:string不能赋值给number(符合预期)
f1O/*<unknown, { a: number, b: string }>*/({ a: 0, b: ''}); // 被允许(不符合预期)

基于f1T的思路,可实现正确工作的可变参数函数:

function fmT<Ts extends unknown[]>(...args: { [K in keyof Ts]: O1<Ts[K]> }) {}
fmT({ a: 0, b: 1 }, { a: '0', b: 2 }); // 报错:number不能赋值给string(符合预期)

双泛型参数场景

单参数场景可直接沿用相同模型:

type O4<T, U> = { a: T, b: NoInfer<T>, c: U, d: NoInfer<U> };
function f1TU<T, U>(arg: O4<T, U>) {}
f1TU({ a: 0, b: 1, c: '', d: 2 }); // 报错:number不能赋值给string(符合预期)

但在可变参数场景下,尝试多种写法均无法解决类型推断问题:

  • 朴素写法:报错 Type 'K' cannot be used to index type 'Us'
function fmTU_naive<Ts extends unknown[], Us extends unknown[]>(...args: {
  [K in keyof Ts]: O4<Ts[K], Us[K]> 
}) {}
  • 键交集写法:破坏元组映射,报错 A rest parameter must be of an array type
function fmTU_inter<Ts extends unknown[], Us extends unknown[]>(...args: {
  [K in (keyof Ts & keyof Us)]: O4<Ts[K], Us[K]> 
}) {}
  • 条件类型写法:破坏推断逻辑,错误允许不符合要求的参数
type AsNumber<S> = S extends `${infer N extends number}` ? N : never;
function fmTU_cond<Ts extends unknown[], Us extends unknown[]>(...args: {
  [K in keyof Ts]: AsNumber<K> extends keyof Us ? O4<Ts[K], Us[AsNumber<K>]> : never;
}) {}
fmTU_cond/*<[number], unknown[]>*/({ a: 0, b: 1, c: '', d: 2 }); // 被允许(不符合预期)
  • 分组泛型参数写法:同样破坏推断逻辑
function fmTU_index<const TUs extends [T: unknown, U: unknown][]>(...args: {
  [K in keyof TUs]: O4<TUs[K][0], TUs[K][1]>;
}) {}
fmTU_index/*<[T: unknown, U: unknown][]>*/({ a: 0, b: 1, c: '', d: 2 }); // 被允许(不符合预期)

最终解决方案

通过辅助类型从O4<unknown, unknown>中推断出合法的O4类型,实现可用的可变参数函数:

const TS_ERROR = Symbol();
type TSError<Msg extends string> = { [TS_ERROR]: Msg };

type InferO4<O extends O4<unknown, unknown>> =
  O extends O4<unknown, unknown> ?
    O['a'] extends infer T ?
      O['b'] extends T ?
        O['c'] extends infer U ?
          O['d'] extends U ?
            O4<T, U> :
          TSError<'Type O[\'d\'] is not assignable to type O[\'c\']'> : 
        never :    
      TSError<'Type O[\'b\'] is not assignable to type O[\'a\']'> :
    never :
  TSError<'Type O is not assignable to type O4<unknown, unknown>' >;

type InferO4s<Os extends O4<unknown, unknown>[]> = { [K in keyof Os]: InferO4<Os[K]> };

function fmO_helper<
  Os extends O4<unknown, unknown>[],
  Is = InferO4s<Os>
>(
  ...args: Os & InferO4s<Os>
) {};

fmO_helper(
  { a: 0, b: 1, c: '0', d: '1'},
  { a: Symbol(), b: 0, c: 0, d: 1}
);
// Is: [O4<number, string>, TSError<"Type O['b'] is not assignable to type O['a']">](符合预期)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 16:50:56