@ typescript-eslint проверка строгих логических выражений на ложное значение

Недавно у меня возникла проблема с тройной проверкой number | undefined var на undefined, но из-за того, что я не уделял внимания при написании кода, когда число было 0, он ошибочно обвинил его в неопределенном значении.

Затем я узнал о строго-логические-выражения Правило ESLint.

Выглядит очень полезно и безопасно, но, учитывая этот пример:

const text: string | undefined = stringOrUndefined1 || stringOrUndefined2 || undefined; // the strings can be empty
if (!text) // I was doing it this way to check if the value was falsy. With the new rule, it complains.
  return;
if (text === undefined || text === '') // This works, but is 4x the length of the one above. I don't want to write the var name more than once
if (!!text == false) // "Unexpected nullable string value in conditional. Please handle the nullish/empty cases explicitly."
if (!!!text) // Same warn as above

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

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


person Henrique Bruno    schedule 21.11.2020    source источник
comment
Цель правила строгих логических выражений - предупреждать о неявных преобразованиях в логические; правдивость или ложность имеют значение только тогда, когда вам действительно нужны эти неявные преобразования. !!text требует неявного преобразования в логическое значение для первого применяемого !; неясно, при каких обстоятельствах вы хотите получить предупреждение, а при каких - нет.   -  person kaya3    schedule 21.11.2020
comment
Поскольку ответы здесь действительны, они действительно недостаточно хороши, чтобы их можно было использовать, не комментируя код, чтобы объяснить, почему они используются. Я думаю, что лучший вариант - проверить ложные значения - это просто и логично text == false, как позволяет JS. Однако в Typescript есть уже выпущенная ошибка, которая не позволяет этого.   -  person Henrique Bruno    schedule 09.12.2020


Ответы (3)


Вы можете попробовать использовать нулевой оператор объединения (_1 _) вот так:

if (!(text ?? '')) {}

text ?? '' оценивается как '', если это undefined, и text в противном случае.

Это эквивалентно следующему:

if (!(text !== null && text !== undefined ? text : '')) {}
person cherryblossom    schedule 21.11.2020
comment
Вероятно, это лучший ответ для данного конкретного случая. Это означает, что ваш код ясен и ясен. Использование оператора ?? делает ваше условное выражение явно означающим, что я обрабатываю нулевой случай точно так же, как и случай пустой строки. - person Brad Zacher; 25.11.2020
comment
Правило strict-boolean-types запрещает использование не-логических типов в выражениях, где ожидается логическое значение, поэтому оно должно жаловаться на выражение !(text ?? ''), поскольку text ?? '' имеет тип string, а не boolean. - person kaya3; 25.11.2020
comment
@ kaya3 По умолчанию _ 1_ равен true, что позволяет использовать строки в логических выражениях. Это безопасно, потому что существует только одно ложное значение (''). - person cherryblossom; 25.11.2020
comment
Понятно. По крайней мере, если эта опция отключена, вы можете вместо этого написать (text ?? '') != ''. - person kaya3; 25.11.2020

Если вы хотите проверить истинность значения, несмотря на то, что strict-boolean-expressions включен, вы можете определить вспомогательные функции для этой цели:

type Falsy = 0 | '' | false | null | undefined

function truthy<T>(x: T): x is Exclude<T, Falsy> {
    return !!(x as any);
}

function falsy<T>(x: T): x is T & Falsy {
    return !(x as any);
}

Затем вы можете написать if(truthy(str)) { ... } или if(falsy(str)) { ... }, где вы хотите использовать эти тесты.

Обратите внимание, что определение типа Falsy здесь неполное; например, когда T равно number, тогда falsy сузит x до буквального типа 0, когда NaN также является возможным ложным значением. К сожалению, обойти это невозможно, поскольку Typescript не имеет буквального типа NaN; это будет проблемой только в том случае, если вы ожидаете в своем коде значений NaN.

person kaya3    schedule 21.11.2020
comment
Не думаю, что это хорошее решение. Смысл правила strict-boolean-expressions состоит в том, чтобы гарантировать, что ваши проверки выполняются строго и явно. Определение этих функций просто работает вокруг правила - в этот момент вы также можете разрешить строки, допускающие значение NULL (github.com/typescript-eslint/typescript-eslint/blob/master/) или просто отключите правило - person Brad Zacher; 25.11.2020
comment
@BradZacher Я думаю, if(truthy(str)) довольно четко описывает, что он делает, не так ли? - person kaya3; 25.11.2020
comment
Существует одна очевидная проблема, я вижу: эти функции типа не понимают, что означает, что они не будут правильно Уточнить переменные (пример: typescriptlang.org/play?#code/) - person Brad Zacher; 25.11.2020
comment
Я лично не думаю, что это ясно. truthy(str) может означать любое количество вещей, одна из которых заключается в том, что я явно обрабатываю пустую и пустую строку как ложные. По-прежнему неясно, решаете ли вы дела явно или просто ленились. Каждая строка кода написана один раз, но будет прочитана много-много раз. Из-за этого вы должны оптимизировать код, прежде всего, для ясности, ясности и удобочитаемости. Чтобы уточнить: IMO всегда лучше использовать 10 дополнительных нажатий клавиш и быть ясным и явным, чем сэкономить 10 и быть двусмысленным. - person Brad Zacher; 25.11.2020
comment
Язык Javascript определяет, какие значения являются правдивыми, а какие - ложными - для функций с такими именами было бы ошибкой делать что-либо еще. Трудно представить, как можно более четко определить, является ли значение истинным, чем вызвать функцию, имя которой говорит, что это именно то, что она проверяет. developer.mozilla.org/en-US/docs/Glossary/Truthy - person kaya3; 25.11.2020
comment
Отсутствие сужения шрифта - хороший момент, поэтому я отредактировал ответ, чтобы его поддержать. - person kaya3; 25.11.2020
comment
Трудно представить, как можно более четко определить, является ли значение истинным --- путем явной проверки! x != null && x !== '' яснее, поскольку здесь нет никакой двусмысленности. Вы четко и явно обработали оба ложных случая, и никто не может неправильно это понять, поскольку они не понимали ошибку линта, они взламывали линтер или, может быть, они не осознавали, что '' был ложным. Именно этого вы и хотите от кода - ясного и недвусмысленного. - person Brad Zacher; 25.11.2020
comment
Ваше предложение включено в вопрос как пример того, что не является тем, что ищет OP: Это работает, но в 4 раза длиннее, чем указано выше. Я не хочу писать имя переменной более одного раза. Однако, если имя falsy недостаточно явное для вас, было бы тривиально переименовать функцию во что-то более описательное, на ваш взгляд. - person kaya3; 25.11.2020

Как уже упоминали другие, суть strict-boolean-expressions в том, чтобы помочь убедиться, что вы явно обрабатываете каждый случай, чтобы вы случайно не пропустили некоторые дела.

Ответ @ cherryblossom - это один из способов сделать это кратко и ясно - он показывает, что вы намеренно обрабатываете пустые и пустые строковые случаи одинаково.

Если в вашем проекте все в порядке с произвольной проверкой нулевых строк - вы можете соответствующим образом перенастроить правило: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/strict-boolean-expressions.md#allownullablestring


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

Большинство IDE (например, VSCode) имеют возможность добавлять шаблонные фрагменты, если вы так склонны экономить нажатия клавиш.

person Brad Zacher    schedule 24.11.2020