TypeScript中如何检查函数参数是否为可选参数?
判断函数参数是否为可选类型
我们先明确核心问题:通过Parameters<typeof saySomething>[0]获取到的参数类型是string | undefined,但这个类型无法区分它是来自可选参数thingToSay?: string,还是来自必填的联合类型参数thingToSay: string | undefined。因此需要从函数的参数元组结构本身入手,实现一个IsOptional工具类型来判断指定位置的参数是否为可选。
实现IsOptional工具类型
下面是一种可行的实现方式,通过对比参数元组在指定位置变为必填后的兼容性来判断是否可选:
// 替换元组指定索引位置的类型为新类型 type ReplaceIndex<T extends any[], Index extends number, NewType> = T extends [...infer Head, infer _] ? Head['length'] extends Index ? [...Head, NewType] : ReplaceIndex<Head, Index, NewType> : never; // 判断函数指定索引的参数是否为可选 type IsOptional<Fn extends (...args: any[]) => any, Index extends number> = Parameters<Fn> extends ReplaceIndex<Parameters<Fn>, Index, Exclude<Parameters<Fn>[Index], undefined>> ? false : true;
使用示例
针对你的示例函数:
function saySomething(thingToSay?: string) { console.log(thingToSay || 'Hello'); } // 判断第0位参数是否可选,结果为true type ThingToSayIsOptional = IsOptional<typeof saySomething, 0>;
再对比必填的联合类型参数:
function saySomethingRequired(thingToSay: string | undefined) { console.log(thingToSay || 'Hello'); } // 判断第0位参数是否可选,结果为false type ThingToSayIsOptional2 = IsOptional<typeof saySomethingRequired, 0>;
原理说明
ReplaceIndex工具类型会将参数元组中指定索引的位置,替换为排除undefined后的类型(也就是该参数的必填版本)。- 如果原参数元组能赋值给这个“必填版本元组”,说明原参数本身就是必填的(即使允许传入
undefined,但不能省略),返回false。 - 如果不能赋值,说明原参数是可选的(可以省略,因此无法适配必填版本的元组),返回
true。
内容的提问来源于stack exchange,提问作者kohloth
相关产品推荐
相关产品推荐

