我不知道如何声明功能臂的第二个参数进行正确的类型检查,我的意思是,如果有人向功能臂的第一个参数发送为“ foo1”,则第二个参数应仅可能是:{{1 }}。如果为“ foo2”,则为(number) => void
。
(string) => void
答案 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
希望对您有帮助。祝你好运!