如何将类的类型筛选为仅接受无参数的函数?
如何在TypeScript中严格筛选无参数且返回void的函数属性?
这个问题的根源在于TypeScript的函数类型兼容性规则:() => void会匹配任何返回void(或兼容void)的函数,哪怕它带有参数——因为TypeScript允许你调用函数时忽略多余的参数,同时返回void的函数可以接受任何返回值(只要你不使用该返回值)。
要实现严格筛选无参数且返回void的函数,我们需要调整类型判断逻辑,确保函数的参数个数、类型和返回值完全匹配。这里有两种可行的方案:
方案1:双向extends实现严格类型匹配
通过让目标函数类型和类属性的函数类型互相赋值(即双向extends判断),只有当两者完全兼容时才保留该属性键:
class Nandar { stuff: string | null = null; doSomething(a: string, b: string): void { console.log(`${a},${b}`); } nothing(): void { console.log('nothing'); } } // 修改后的Delegates类型,添加双向extends判断 type Delegates<Type, Fn> = keyof { [K in keyof Type as (Type[K] extends Fn ? (Fn extends Type[K] ? K : never) : never)]: K }; // 测试:仅匹配doSomething type StringDelegate = (a: string, b: string) => void; type StringKeys = Delegates<Nandar, StringDelegate>; // "doSomething" // 测试:仅匹配nothing type NothingDelegate = () => void; type NothingKeys = Delegates<Nandar, NothingDelegate>; // "nothing"
方案2:利用工具类型直接检查参数和返回值
如果你只针对无参数、返回void的场景,可以直接用Parameters和ReturnType工具类型明确判断:
type StrictVoidNoArgDelegates<Type> = keyof { [K in keyof Type as (Type[K] extends (...args: any[]) => void ? Parameters<Type[K]> extends [] ? K : never : never)]: K }; // 测试:仅匹配nothing type OnlyNothingKeys = StrictVoidNoArgDelegates<Nandar>; // "nothing"
为什么原代码不生效?
原代码中仅使用Fn extends Type[K]判断,对于() => void来说,(a: string, b: string) => void是符合这个条件的——因为TypeScript允许你把多参数函数赋值给少参数的函数类型(调用时忽略多余参数)。而双向extends判断会排除这种情况,因为() => void无法赋值给(a: string, b: string) => void(后者要求必须传入两个参数)。
内容的提问来源于stack exchange,提问作者Joseph Zabinski
相关产品推荐
相关产品推荐

