能否让TypeScript编译器对不符合参数必填要求的函数赋值报错?
能否让TypeScript在函数赋值不符合参数必填要求时抛出错误?
需求:希望TypeScript编译器在函数赋值不符合原函数的参数必填要求时抛出错误,示例代码如下:
function f(r: number, o?: string) {} type HasRequiredProps<F> = F extends (...args: infer A) => any ? A['length'] extends 1 | 0 ? false : true : false; type R = HasRequiredProps<typeof f> extends true ? (p: number) => void : (p?: number) => void // 此处期望触发错误,但实际没报错 const ff: R = function () { }
这个需求可以实现,但你当前的类型逻辑存在两个问题:
HasRequiredProps仅通过参数数组长度判断是否有必填项,逻辑不准确——比如参数长度为2但其中只有1个必填项的情况,它会误判;- TypeScript默认的函数赋值遵循逆变规则:允许少参数的函数赋值给多参数的类型(因为调用时会传入足够参数,少参数的函数会忽略多余部分),所以即使
R定义为(p: number) => void,赋值无参函数也不会报错。
修正方案
要实现严格的必填参数检查,需要先提取原函数的所有必填参数,再约束赋值的函数必须包含这些参数。示例代码如下:
function f(r: number, o?: string) {} // 提取函数的所有必填参数类型 type RequiredArgs<F> = F extends (...args: infer A) => any ? FilterRequired<A> : never; // 递归过滤出数组中的必填项(排除可选参数) type FilterRequired<T extends any[]> = T extends [infer First, ...infer Rest] ? First extends undefined ? FilterRequired<Rest> : [First, ...FilterRequired<Rest>] : []; // 根据原函数是否有必填参数,定义目标类型 type R = RequiredArgs<typeof f> extends [] ? (p?: number) => void : (...args: RequiredArgs<typeof f>) => void; // 此处会触发TypeScript错误,符合预期 const ff: R = function () {};
说明
RequiredArgs和FilterRequired组合作用,精准提取原函数中所有必填的参数类型(比如示例中会提取出[number]);- 当原函数有必填参数时,
R会要求赋值的函数必须接收这些必填参数,打破了默认的逆变规则限制,从而在赋值不符合要求的函数时抛出错误。
内容的提问来源于stack exchange,提问作者doox911
相关产品推荐
相关产品推荐

