TypeScript, объект с пропеллером типа bool или () => bool, как обращаться? - PullRequest
1 голос
/ 15 апреля 2020

У меня есть приложение Vue. Я конвертирую ваниль JS в TypeScript, и у меня есть этот шаблон; У меня есть компонент, который принимает элемент свойства, который представляет собой объект с несколькими свойствами, следующие схеме:

type Button = {
    variant?: 'string' | function(): string;
    ...others...
}

Все работает по идее, что он принимает строку или функцию, которая возвращает строку (это также работает for booleans et c ...)

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

private finalize<K extends keyof Button>(item: Button, key: K, target: Button["target"]): Button[K] {
  let finalized:Button[K]? = null;
  if (identify(item).isObject()) {
    if (identify(item[key]).isFunction()) {
      finalized = item[key](target);
    } else {
      finalized = item[key];
    }
  } else if (item) {
    finalized = item;
  };
  return finalized;
}

Моя проблема в том, что я хочу сузить возвращаемый тип из объединения, например - string | () => string -, до string. Вместо этого мой возвращаемый тип функции завершения по-прежнему string | () => string. Как я понимаю, что TS понимает, что если это функция, то она выполнит ее

1 Ответ

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

Хорошее решение, которое будет работать для любого типа возврата:

function isCallable<T>(value: T | (() => T)): value is (() => T) {
  return value instanceof Function;
}

И тогда вы будете использовать этот способ:

let myValue: string | () => string;

// Here, myValue should be assigned somethign, otherwise TypeScript will
// complain that it's used before it gets anything assigned. Let's give it
// something and manually type it as `any` so TypeScript is still in the dark
// regarding its true type.
myValue = "hello" as any;

if (isCallable(myValue)) {
  // myValue is narrowed as a function that returns a string
} else {
  // myValue is narrowed as a string
}

Это будет работать с любым типом, спасибо к универсальности функции isCallable. Он принимает все, что либо типа (T), либо функцию, которая возвращает тип T. Как только вы вызываете его, и благодаря ключевому слову is в его подписи, TypeScript может сузить тип данной переменной.

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