能否从元组参数推断函数参数的参数长度?
能否从元组参数推断函数参数的参数长度?
嘿,这问题我熟!当然能从元组参数推断出函数参数的长度和对应类型,咱们直接对着你的代码来改,一看就懂。
首先得明确下咱们要用的Ref类型(你代码里没明确定义,先补上):
type Ref<T> = { val: T };
你原来的multiplex函数泛型定义有点小问题,导致TypeScript没法把refs的元组长度和fn的参数长度关联起来。咱们调整下泛型和参数类型,就能让TypeScript自动完成推断:
function multiplex<R extends readonly Ref<any>[], T>( refs: R, // 核心:从元组R里提取每个Ref的val类型,组成对应长度的参数元组 fn: (...args: { [K in keyof R]: R[K] extends Ref<infer V> ? V : never }) => T ) { // 这里加个类型断言,让map返回的数组匹配我们需要的参数元组类型 const vals = refs.map(ref => ref.val) as { [K in keyof R]: R[K] extends Ref<infer V> ? V : never }; console.log('got:', fn(...vals)); }
咱们来测试下你原来的调用场景,TypeScript会自动帮你做这些:
const ref1: Ref<number> = { val: 42 }; const ref2: Ref<string> = { val: 'world peace' }; // 这里val1会被自动推断为number,val2为string,而且必须传2个参数,多传少传都会报错! multiplex([ref1, ref2], (val1, val2) => { createWorldPeace(val1, val2); return val1 + val2.length; });
为啥这能行?
- 泛型
R会被TypeScript自动推断为具体的元组类型(比如上面例子里的[Ref<number>, Ref<string>]),而不是宽泛的Ref<any>[]数组类型 - 用映射类型
{ [K in keyof R]: ... }遍历元组的每个索引,把每个Ref的val类型提取出来,组成一个和R长度完全一致的新元组,作为fn的参数类型 - 用
(...args: 元组类型)的写法,强制fn的参数数量、顺序、类型都和refs的元组完全匹配
要是你不想用readonly,把泛型里的readonly去掉也没问题,但加readonly能兼容更多场景(比如传入用as const断言的数组)。
备注:内容来源于stack exchange,提问作者user29889977
相关产品推荐
相关产品推荐

