typescript 如何将类的类型限制为不接受参数的函数?

mrwjdhj3  于 2023-01-21  发布在  TypeScript
关注(0)|答案(1)|浏览(113)

Playground示例
假设我有这样一个类:

class Nandar {
    stuff: string | null = null;
    doSomething(a: string, b: string): void {
        console.log(`${a},${b}`);
    }
    nothing(): void {
        console.log('nothing');
    }
}

我可以使用这个类型来提取类的属性,将键缩小到仅一个给定的函数签名:

type Delegates<Type, Fn> = keyof {
    [K in keyof Type
    as Fn extends Type[K] ? K : never]: K
};

例如:

type StringDelegate = (a: string, b: string) => void;

const delegate: Delegates<Nandar, StringDelegate>; // delegate's only possible value is 'doSomething'

如果我想缩小到Nandar.nothing的类型,虽然,我有一个问题。
使用类似代码:

type NothingDelegate = () => void;
const delegate: Delegates<Nandar, NothingDelegate>; // delegate's values can be 'doSomething' or 'nothing'

我不想"做某事";我只想要'nothing'。基本上,Typescript接受() => void来引用任何函数,使用任何数量的参数和任何返回类型。这不是我想要Typescript做的:我希望它引用不使用参数并且不返回任何值的函数。
手册上说
返回void的回调类型表示"如果存在返回值,我不会查看它"
但是我确实想查看返回值,并确保它是void,我还想确保函数没有参数,有语法吗?

fnvucqvd

fnvucqvd1#

问题在于,一个函数可以赋值给另一个函数,它不一定需要相同的arity,如果一个函数的参数类型与另一个函数的参数类型匹配,并且唯一的区别是这个函数的参数少,那么它就是可赋值的:

type UhOh = (() => void) extends ((a: string, b: string) => void) ? true : false;
//   ^? true

在这里你可以看到一个没有参数的函数可以赋值给一个有两个参数的函数。为了确保这个函数没有参数,你可以使用参数实用程序类型来检查它是否没有参数:

type NoArgFns<T> = {
    [K in keyof T]: T[K] extends (...args: any[]) => any ? Parameters<T[K]>["length"] extends 0 ? K : never : never
}[keyof T];

type T = NoArgFns<Nandar>;
//   ^? "nothing"

Playground

相关问题