TypeScript - проверить, является ли свойство объекта функцией с заданной сигнатурой - PullRequest
0 голосов
/ 16 мая 2018

У меня есть функция, которая получает свойство от объекта.

// Utils.ts
export function getProperty<T, K extends keyof T>(obj: T, key: string): T[K] {
    if (key in obj) { return obj[key as K]; }
    throw new Error(`Invalid object member "${key}"`);
}

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

getProperty() используется для динамического получения одного из объектовметод и вызвать его.Я попытался:

let property: this[keyof this] = utils.getProperty(this, name);
if (typeof property === 'function') ) { property(conf); }

Но это дает: «Невозможно вызвать выражение, тип которого не имеет подписи вызова. Тип« любой »не имеет совместимых подписей вызова».ошибка.Я понимаю, что свойство, полученное из getProperty(), действительно может быть любого типа, но как убедиться, что это функция с (conf: {}): void сигнатурой?

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

Не похоже, что typeof защита типа существует для типов функций.Кажется, это по замыслу (эта проблема касается instanceof охранников типа, но я предполагаю, что это аналогичные рассуждения).

Однако в TypeScript есть определяемый пользователем типguards , что означает, что вы можете написать функцию, которая сужает тип аргумента так, как вам нравится.Итак, какой тест во время выполнения определит, является ли какое-либо значение x функцией типа (conf: {}) => void?Вы можете проверить, если typeof x === "function", конечно.Это не означает, что функция будет принимать параметр какого-либо определенного типа и ничего не будет возвращать.Может быть, вы просто знаете, что любая функция, которую вы извлекаете из getProperty, будет правильного типа.Если нет, вы должны выяснить, как отличить разницу во время выполнения.(Является ли x.length === 1? Есть ли какая-то другая отличительная особенность?)

Как только вы узнаете свой тест во время выполнения, вы можете создать защиту типа:

function isFunctionOfRightType(x: any): x is (conf: {})=>void {
   return (typeof x === 'function') && (x.length === 1); // or whatever test
}

// ... later

let property: this[keyof this] = utils.getProperty(this, name);
if (isFunctionOfRightType(property)) { property(conf); } // no error now

Надеюсь, что это поможет.Удачи!

0 голосов
/ 16 мая 2018

В вашей сигнатуре функции есть ошибка, параметр key должен иметь тип K, и это даст вам лучший вывод при использовании констант для параметров:

export function getProperty<T, K extends keyof T>(obj: T, key: string): T[K] {
    if (key in obj) { return obj[key as K]; }
    throw new Error(`Invalid object member "${key}"`);
}

let foo = {
    fn (conf: {}): void {}
}
let fn = getProperty(foo, "fn");
fn({}); // callable 

Проблема, когдаВы используете ключ, который является строкой и не проверен во время компиляции, так это то, что компилятор действительно не может вам помочь ни с чем.Это предполагает, что, поскольку вы индексируете мою произвольную строку, тип возвращаемого значения может быть любым допустимым типом поля цели.Нет способа проверить типы параметров функции во время выполнения, так как они будут удалены, вы можете проверить количество параметров, хотя:

let property:  Function = getProperty(this, name) as any;
if (typeof property === 'function' && property.length == 1)  
{ 
    property({}); 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...