Типы Typescript: принять правильный тип обратного вызова в зависимости от другого аргумента - PullRequest
0 голосов
/ 14 апреля 2020

У меня есть JS функция

const fn = (cb, param) => {
  cb(param);
};

, которая должна называться 2 способами (в TS):

const cb0 = () => {};
fn(cb0);

const cb1 = (param: string) => { };
fn(cb1, 'str')

fn ожидания правильно описываются этим type:

interface IFn {
  (cb: (param: string) => void, param: string): void;
  (cb: () => void): void;
}

fnI(cb0); // ok
// fnI(cb1); // correctly does not compile, callback needs an argument
fnI(cb1, 's'); // ok

Таким образом, он проверяет типы на сайтах вызывающих абонентов. Тем не менее, я не могу преобразовать fn в Typescript, поэтому он не требует приведения типов. Более того, кажется, что TS отказывается выводить типы аргументов, поскольку IFn объявляет перегрузки. Лучшее, что я могу сделать, это:

const fn: IFn = <IFn>((cb: (param?: string) => void, param?: string) => {
  cb(param);
});

Проблема в том, что сигнатура реализации менее ограничительна, и следующая реализация явно нарушает утверждения IFn, но нарушение не может быть обнаружено по типу checker.

const fn: IFn = <IFn>((cb: (param?: string) => void, param?: string) => {
  cb(param === undefined ? 'some other string' : undefined);
});

Итак, вопрос в следующем: Можно ли определить fn подпись или IFn, чтобы приведенное выше нарушение утверждений в реализации было бы обнаружено с помощью TypeScript ?

Очевидно, меня не интересуют проверки во время выполнения.

1 Ответ

0 голосов
/ 26 апреля 2020

Попробуйте:

interface IFn {
  (cb: (param: string) => void, param: string): void;
  (cb: () => void): void;
}

const fn: IFn = (
  ...args: [(param: string) => void, string] | [() => void]
) => {
  switch (args.length) {
    case 2: {
      const cb = args[0];
      const param = args[1];

      cb(param);
      break;
    }
    case 1: {
      const cb = args[0];

      cb();
      break;
    }
  }
};

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...