具有适当签名的通用功能

时间:2019-03-20 23:15:46

标签: javascript typescript function generics parameters

我不知道如何声明功能臂的第二个参数进行正确的类型检查,我的意思是,如果有人向功能臂的第一个参数发送为“ foo1”,则第二个参数应仅可能是:{{1 }}。如果为“ foo2”,则为(number) => void

(string) => void

1 个答案:

答案 0 :(得分:2)

首先,请注意parameter names in function types are required,因此必须更改此定义:

interface MyFoo {
    foo1: (x: number) => void; 
    foo2: (x: string) => void;
}

现在,在Bar<Foo>中,我们只需在K方法上使用一个通用参数boom(),因为将为我们指定类型Foo。我不太了解您的用例,因为看起来也许您希望boom()接受可变数量的参数,但这与关于您如何需要一个参数的注释不符。回调函数。因此,我假设boom()接受两个参数:键名和回调函数:

class Bar<Foo> {
    public boom<K extends keyof Foo>(first: K, second: Foo[K]) { }
}

然后是使用方法:

// okay, the callback is (x: number) => void
new Bar<MyFoo>().boom("foo1", (x: number) => console.log(x.toFixed(2)));

// error, the callback is (x: number) => void but should be (x: string) => void
new Bar<MyFoo>().boom("foo2", (x: number) => console.log(x.toFixed(2))); 

顺便说一句,这不会阻止您使用具有非功能属性的界面:

interface MyFoo { age: number }
new Bar<MyFoo>().boom("age", 40); // okay

如果您要求boom()仅在与类似函数的属性对应的键上起作用,那么您将需要一些更高级的conditional types

type KeysMatching<T, V> =
    Extract<keyof T, { [K in keyof T]: T[K] extends V ? K : never }[keyof T]>;

class Bar<Foo> {
    public boom<K extends KeysMatching<Foo, Function>>(first: K, second: Foo[K]) { }
}

// okay, the callback is (x: number) => void
new Bar<MyFoo>().boom("foo1", (x: number) => console.log(x.toFixed(2)));

// error, the callback is (x: number) => void but should be (x: string) => void
new Bar<MyFoo>().boom("foo2", (x: number) => console.log(x.toFixed(2))); 

interface MyFoo { age: number }

// error, "age" is not accepted anymore
new Bar<MyFoo>().boom("age", 40); // error

希望对您有帮助。祝你好运!