Typescript не сможет понять, что ваша фильтрация свойств будет означать, что T[K]
всегда является функцией. Вы можете немного изменить свое ограничение, чтобы указать, что T
расширяет то, что имеет свойства типа ()=>void
function call<
T extends { [P in K]: ()=> void },
K extends keyof T
>(t: T, func: K) {
t[func]();
}
class Test {
prop: string = "";
doStuff(): void {}
}
call(new Test(), "prop") // error
call(new Test(), "doStuff") // ok
Однако обратите внимание, что вы можете рассмотреть возможность использования утверждения в своей исходной функции. Приведенная выше версия, избегая утверждений и сохраняя безопасность типов, не помогает intelisense выяснить, какие возможные значения можно назначить второму параметру, поэтому вместо этого:
Вы получаете это:
Хотя в этом случае обычно следует избегать утверждений, мы уверены, что тип на самом деле будет правильным, потому что у нас есть ограничения на ключ, поэтому эта версия тоже должна быть в порядке:
function call2<
T,
K extends {
[K in keyof T]: T[K] extends ()=> void ? K : never
}[keyof T],
>(t: T, func: K) {
(t[func] as any as ()=> void)();
}