TypeScript如何区分泛型参数void?实现参数数量动态适配
实现泛型参数为void时允许无参、其他类型时必须传参的函数
要实现泛型函数在泛型参数为void时允许传入0个参数,其他类型时必须传入1个对应类型的参数,可以通过函数重载或者条件类型定义参数列表两种方式解决,以下是具体实现:
方法一:函数重载
通过定义多个函数重载签名,分别对应泛型为void和非void的场景,TS会根据调用时的泛型或参数自动匹配对应的签名:
class TestClass<Context = void> { protected context: Context; constructor(context: Context) { this.context = context; } } // 重载1:泛型为void时,无需传入参数 export function genericVoidNeedArgument(): TestClass<void>; // 重载2:泛型为非void类型时,必须传入对应类型的参数 export function genericVoidNeedArgument<Context>(context: Context): TestClass<Context>; // 函数实现(兼容两种场景) export function genericVoidNeedArgument<Context = void>(context?: Context) { return new TestClass(context as Context); } type UserType = { id: string; }; // 符合预期:正常执行(泛型默认是void) genericVoidNeedArgument(); // 符合预期:报错(指定了UserType泛型,必须传参数) genericVoidNeedArgument<UserType>(); // 符合预期:正常执行(传入了正确类型的参数) genericVoidNeedArgument<UserType>({ id: "123" });
方法二:条件类型动态生成参数列表
利用TS的条件类型,根据泛型参数是否为void来动态生成参数列表:
class TestClass<Context = void> { protected context: Context; constructor(context: Context) { this.context = context; } } export function genericVoidNeedArgument<Context = void>( // 当Context是void时参数为空数组,否则为单元素必选参数 ...args: Context extends void ? [] : [context: Context] ): TestClass<Context> { return new TestClass(args[0] as Context); } type UserType = { id: string; }; // 符合预期:正常执行 genericVoidNeedArgument(); // 符合预期:报错 genericVoidNeedArgument<UserType>(); // 符合预期:正常执行 genericVoidNeedArgument<UserType>({ id: "123" });
说明
- 两种方法都能严格约束参数数量:泛型为
void时允许无参,其他类型必须传参,避免了Context | void导致的非void类型可以传void的问题。 - 实现部分的类型断言
as Context是因为TS无法自动推导args[0]的具体类型,需要手动指明。
内容的提问来源于stack exchange,提问作者clucle
相关产品推荐
相关产品推荐

