Как использовать функцию правильного типа для универсальной функции?

#typescript #type-safety

Вопрос:

Я пытаюсь исправить @typescript-eslint/ban-types ошибки с ворсом:

предупреждение Не используйте Function в качестве типа @typescript-eslint/ban-типы

Я согласен, что Function это небезопасный тип, и его следует заменить соответствующим типом функции, например () => void .

Но мой код немного сложен, и я понятия не имею, как избежать этого здесь, так как я использую typeof , что возвращает a Function .

Вот упрощенная версия моего кода. Полная версия находится здесь.

 function start<T>(args: unknown[], couldBeAFunction: T) {
  if (typeof couldBeAFunction === 'function') {
    runFunction(args, couldBeAFunction); // couldBeAFunction now is a Function
  }
}

function runFunction<T extends Function>(args: unknown[], target: T) {
  target.apply(args, args);
}
 

Я не могу заменить runFunction<T extends Function> на runFunction<T extends (...args: unknown[]) => unknown> , иначе при вызове я получу следующую ошибку runFunction :

Аргумент типа «T amp; Функция» не может быть назначен параметру типа «(…args: неизвестно[]) => неизвестно». Тип «Функция» не соответствует подписи «(…args: неизвестно[]): неизвестно».ts(2345)

Как я могу решить эту ошибку с ворсом?

Ответ №1:

Вы можете использовать typeguard:

 type Fn = (...args: unknown[]) => unknown

const isFn = (fn: unknown): fn is Fn => typeof fn === 'function'

function start<T>(args: unknown[], couldBeAFunction: T) {
  if (isFn(couldBeAFunction)) {
    runFunction(args, couldBeAFunction); // couldBeAFunction now is a Function
  }
}

function runFunction<T extends Fn>(args: unknown[], target: T) {
  target.apply(args, args);
}
 

Игровая площадка

Комментарии:

1. Спасибо, но в моем конкретном случае я не могу изменить общие ограничения, потому bind что это реализация интерфейса со следующим типом: bind<T>(context: Context, target: T): T;

2. пожалуйста, поделитесь своей конкретной реализацией

3. Функции, над которыми я работаю: github.com/open-telemetry/opentelemetry-js/blob/… Вот если bind в интерфейс: github.com/open-telemetry/opentelemetry-js-api/blob/…