Машинопись. Фильтрация функциональных свойств и «Невозможно вызвать выражение, тип которого не имеет сигнатуры вызова». - PullRequest
0 голосов
/ 28 апреля 2018

Я реализую функцию call, которая получает объект и имя свойства, а затем вызывает функцию, находящуюся в переданном объекте, в переданном свойстве.

function call<
    T,
    K extends {
        [K in keyof T]: T[K] extends Function ? K : never
    }[keyof T],
    >(t: T, func: K) {

    t[func]();
}

Похоже, что TS доволен этим и правильно фильтрует свойства (нет prop, доступно только do):

enter image description here

Но это также показывает ошибку в строке, где я вызываю функцию: t[func]();:

Cannot invoke an expression whose type lacks a call signature.
Type '{}' has no compatible call signatures.

Я обнаружил похожую проблему [Вывод типов с использованием сопоставленных типов и обобщений] однако он закрыт как дубликат другой проблемы [Сигнатуры вызовов типов объединения] . Очевидно, проблема заключается в том, что второй универсальный параметр на самом деле является типом объединения всех имен свойств, которые удовлетворяют условию.

Есть ли другие способы исправить это, кроме приведения к any?

PS: Детская площадка

1 Ответ

0 голосов
/ 28 апреля 2018

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 выяснить, какие возможные значения можно назначить второму параметру, поэтому вместо этого:

enter image description here

Вы получаете это: enter image description here

Хотя в этом случае обычно следует избегать утверждений, мы уверены, что тип на самом деле будет правильным, потому что у нас есть ограничения на ключ, поэтому эта версия тоже должна быть в порядке:

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)();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...