Может ли TypeScript выводить тип различаемого объединения через «извлеченные» логические логики c? - PullRequest
1 голос
/ 13 апреля 2020

Я чаще использую дискриминационные союзы (ДУ) и полюбил их. У меня, однако, есть одна проблема, которую я не могу решить. Если вы встроите логическую проверку для DU, вы можете положиться на TypeScript (TS), чтобы автоматически определить тип для вас. Однако, если вы извлечете логическую проверку, TS больше не сможет сузиться до указанного подтипа c DU. Мне известны средства защиты типов, но я хотел бы знать, почему компилятор не поддерживает извлеченные онлайн-проверки, в частности.

Это известное ограничение? Должен ли я подать запрос об ошибке / функции?

Пример здесь (w / TypeScript Playground Link ):

type A = { type: "A"; foo: number };
type B = { type: "B"; bar: string };
type DU = A | B;

const checkIt = (it: DU) => {
  const extractedCheck = it.type === "A";

  if (extractedCheck) {
    // it does not get narrowed
    console.log(it.foo); // Error: Property 'foo' does not exist on type 'DU'.
  }

  if (it.type === "A") {
    // but this is fine
    console.log(it.foo);
  }
};

Ответы [ 2 ]

2 голосов
/ 13 апреля 2020

Существует существующий запрос функции в microsoft / TypeScript # 12184 , позволяющий "сохранять" результаты защиты типа в "именованном значении для последующего использования. Запрос открыт, но указан как «revisit», потому что не существует очевидного способа реализовать его эффективным способом. Слово от ведущего архитектора языка :

Это потребовало бы, чтобы мы отслеживали, какие эффекты дает конкретное значение для одной переменной для других переменных , что добавило бы значительную сложность (и связанное с этим снижение производительности) анализатору потока управления. Тем не менее, мы будем хранить это как предложение.

Так что я не ожидаю увидеть такую ​​функцию в языке в ближайшее время, к сожалению.


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


Хорошо, надеюсь, это поможет; удачи!

1 голос
/ 13 апреля 2020

В настоящее время нет, как упомянуто @jcalz, однако есть минимальный обходной путь, который вы всегда можете применить, чтобы преодолеть эту проблему.

Хитрость заключается в том, чтобы сделать extractCheck функцией, которая возвращает предикат типа .
(см. https://www.typescriptlang.org/docs/handbook/advanced-types.html#user -defined-type-guard )

Рабочий пример приведен ниже:

type A = { type: "A"; foo: number };
type B = { type: "B"; bar: string };
type DU = A | B;

const checkIt = (it: DU) => {
  // Make `extractCheck` a function 
  const extractedCheck = (it: DU): it is A => it.type === "A";

  if (extractedCheck(it)) {
    console.log(it.foo);  // No error
  }
};
...