TypeScript中augment函数未传actions时类型推断异常解决咨询
解决TypeScript中
augment函数不传参数时的类型推断问题 问题根源
当不传入actions参数时,TypeScript会将泛型A的类型推断为keyof T(因为A extends keyof T,无更具体约束时会取类型上限),导致Pick<T, A>等价于T,实例意外拥有所有属性。
方案一:给泛型A设置默认类型never
这是最简洁的解决方式,给A指定默认类型为never,不传actions时A会使用默认值,而Pick<T, never>会生成空类型,实例就不会包含T的任何属性。
修改后的代码:
interface Foo { a: number; b: string; } function augment<T>() { // 为泛型A添加默认类型never return <A extends keyof T = never>(actions?: A[]) => { const C = class { // 原有业务代码 }; return C as unknown as new () => InstanceType<typeof C> & Pick<T, A>; }; } // 测试验证 const Class = augment<Foo>()(["a", "b"]); const instance: InstanceType<typeof Class> = new Class(); // ✅ instance.a 和 instance.b 正常可用 const Class2 = augment<Foo>()([]); const instance2: InstanceType<typeof Class2> = new Class2(); // ✅ instance2 不包含a、b属性 const Class3 = augment<Foo>()(); const instance3: InstanceType<typeof Class3> = new Class3(); // ✅ instance3 不包含a、b属性,符合预期
方案二:使用函数重载明确参数与返回类型
如果需要更清晰的类型逻辑区分,可以用函数重载分别定义「不传参数」和「传参数」两种场景的类型:
interface Foo { a: number; b: string; } function augment<T>() { // 重载1:不传actions时,返回的类实例不包含T的任何属性 function impl(): new () => InstanceType<typeof C>; // 重载2:传入指定属性数组时,返回包含对应属性的实例类型 function impl<A extends keyof T>(actions: A[]): new () => InstanceType<typeof C> & Pick<T, A>; // 核心实现 function impl<A extends keyof T>(actions?: A[]) { const C = class { // 原有业务代码 }; return C as unknown as new () => InstanceType<typeof C> & (A extends never ? {} : Pick<T, A>); } return impl; } // 测试验证效果与方案一一致
总结
方案一通过泛型默认值快速解决问题,代码改动极小;方案二通过重载让类型逻辑更明确,适合需要区分多种参数场景的复杂情况,可根据实际需求选择。
内容的提问来源于stack exchange,提问作者Guid
相关产品推荐
相关产品推荐

