Typescript - встроенная неопределенная проверка не работает (объект, возможно, 'undefined'.ts (2532)) - PullRequest
0 голосов
/ 03 мая 2019

Я получаю следующую ошибку машинописи:

const myFunction = (
  param1: string | undefined,
  param2: { someProp: string } | undefined
) => {
  if (!param1 && !param2) {
    return;
  }

  // Here I get the following Typescript error:
  //  (parameter) param2: { someProp: string } | undefined
  //  Object is possibly 'undefined'.ts(2532)
  const param3 = param1 ? param1 : param2.someProp;
};

следующие работы:

const param4 = param1 ? param1 : param2 ? param2.someProp : null;

, но, кажется, излишне проверять наличие нуля или неопределенности дважды.

Я должен упомянуть, что опция strictNullChecks имеет значение true в параметрах компилятора, и хочу сохранить его следующим образом.

Есть идеи, почему я получаю эту ошибку?

Вот CodeSandbox с кодом: https://codesandbox.io/s/jn2mp01q2v

Ответы [ 2 ]

2 голосов
/ 03 мая 2019

Грустная правда о компиляторе TypeScript состоит в том, что он просто не такой умный, как человек (во всяком случае, с TypeScript 3.4), и поэтому его анализ потока управления является лишь бледной тенью анализа вы можете выполнить самостоятельно. Конечно, он очень последовательн в своем анализе, в то время как мой имеет тенденцию ухудшаться, когда я недавно не ел.

Если вы выполняете проверку переменной типа объединения, которая полностью исключает одну или несколько составляющих этого объединения, компилятор с радостью сузит тип переменной для вас:

param1.charAt(0); // error, possibly undefined
if (!param1) return;
param1.charAt(0); // okay now

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

if (!param1 && !param2) return;

- это вероятность того, что param1 и param2 могут быть undefined одновременно. Вы взяли две ранее независимые переменные и сопоставили их друг с другом. Который компилятор не отслеживает. Поскольку param1 и param2 могут по-прежнему иметь значение undefined (только не одновременно), компилятор обрабатывает их как все еще независимые, и у вас остается проблема.

Вы можете сделать то, что предложил другой ответ, и использовать утверждение типа , которое предназначено для случаев, когда вы умнее компилятора и не хотите пытаться провести компилятор через задачу понимания того, что вы уже знаете:

const param3 = param1 ? param1 : param2!.someProp; // I'm smarter than the compiler ?

Обратите внимание, что я использовал оператор ненулевого подтверждения !, который, возможно, является наиболее кратким способом, чтобы утверждать ваше превосходство над машиной. Также помните, что такие утверждения небезопасны, так как вы можете быть ошибочными в отношении вашего превосходства. Так что делайте что-то подобное только после двойной и тройной проверки, что param2 не может быть undefined.


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

const param3 = param1 || (param2 ? param2.someProp : undefined);
if (!param3) return;
param3.charAt(0); // string

Это будет работать для вас, и вы проверяете каждый параметр только один раз. Переменная param3 имеет тип string | undefined и равна undefined, только если param1 и param2 ложные. Каждый шаг в этом коде полностью устраняет составляющие объединения для каждой переменной, не оставляя коррелированных типов, которые могут запутать компилятор.

Любое решение должно работать на вас. Надеюсь, это поможет; удачи!

0 голосов
/ 03 мая 2019

Поскольку вы указали два типа для param2, один является объектом, а другой не определен.Вы должны дать как

const param3 = param1?param1: (param2 как любой) .someProp;

тогда он должен работать.

...