// code snippet
function valueOrDefault(a?: string) {
return a || "the default";
}
с конфигурацией tslint.json
:
{
"defaultSeverity": "error",
"extends": [
"tslint:all"
]
}
Получение отчета о 2-х ошибках:
strict-boolean-expressions This type is not allowed in the operand for the '||' operator because it could be undefined. Only booleans are allowed.
strict-boolean-expressions This type is not allowed in the operand for the '||' operator because it is always truthy. Only booleans are allowed.
Об ошибках не сообщается. Я использую логический оператор ||
чтобы указать значение по умолчанию для параметра (я знаю, что могу использовать объявление параметра функции по умолчанию, этот фрагмент предназначен только для иллюстрации общей проблемы). boolean
нигде нет: ни вход, ни выход выражения.
Мысли? Молитвы? Предложения о том, где / как начать?
@marcind, можете ли вы привести примеры того, как он должен вести себя иначе, чем
Извините, какая часть моей первоначальной заявки неясна?
Я полагаю, что моя точка зрения состоит в том, что это правило должно выполняться только в «логическом контексте». Я могу представить себе два случая:
if
, while
или for
boolean
.Правило не должно выполняться, когда я пытаюсь предоставить значение по умолчанию или оценку короткого замыкания.
const a: string = potentiallyUndefinedString || "the default";
const a: string | undefined = potentiallyUndefinedObject && potentiallyUndefinedObject.getString()
@marcind примеры из вашего последнего поста будут работать, если вы используете опцию "allow-undefined-union"
.
Другая часть вашего запроса должна быть отдельным правилом с именем strict-boolean-conditions
которое проверяет только if
, for
, while
, do ... while
и условное выражения ( x ? y : z
).
Я могу представить, что он будет проверять только тип всего условия, а не его составляющие:
function foo(a: boolean, b?: boolean) {
if (b || a) {} // passes, result is always boolean
if (b && a) {} // fails, result is boolean | undefined
if (a || b) {} // fails, result is boolean | undefined
if (a || !!b) {} // passes
}
Возможно, это может быть вариант для существующего правила вместо нового правила ...
На мой взгляд, strict-boolean-expressions
должен проверять только левый операнд &&
и ||
. Эти операторы (по сути) являются сахаром для троичных: a && b
равно a ? b : a
, а a || b
равно a ? a : b
. Когда вы думаете об этом в этих терминах, игнорирование RHS имеет большой смысл, и это приведет к тому, что поведение короткозамкнутых операторов будет соответствовать поведению троичных.
Затем , если все это находится внутри if / for / while, strict-boolean-conditions
может вступить в игру и проверить общее выражение. Я думаю, что это охватит все полезные случаи, и я смогу снова включить это правило.
Код, который пометил это как проблему для меня, был документированным общим шаблоном React :
function Foo(props: { showToggle: boolean }) {
return <div>{props.showToggle && <Toggle />}</div>;
}
ERROR: 2:36 strict-boolean-expressions This type is not allowed in the operand for the '&&' operator because it is always truthy. Allowed types are boolean, null-union, undefined-union, string, or number.
@ajafff Его код не проходит для меня
export function valueOrDefault(a?: string) {
return a || "the default";
}
"strict-boolean-expressions": [true, "allow-null-union", "allow-undefined-union", "allow-string", "allow-number", "allow-mix"]
ERROR: 2:15 strict-boolean-expressions This type is not allowed in the operand for the '||' operator because it is always truthy. Allowed types are boolean, null-union, undefined-union, string, or number.
Намерение выражения является условным для LHS, поэтому мое предложение игнорировать RHS также решило бы его проблему.
Я согласен с тем, что проверка правого места &&
и ||
является ошибкой.
Я также склонен ослабить проверки для LHS &&
, ||
и операнда !
. Их следует только проверять, всегда ли выражение правдиво или всегда ложно.
Это оставляет только условия if
, for
, while
, do ... while
и условные выражения для строгой проверки, чтобы разрешить только логические значения (или все, что настроено ). Мысли @adidahiya?
В настоящее время включение этого правила с доступными параметрами конфигурации потребует нескольких дней работы с нашей базой кода. :(
Я включил его, надеясь, что это предотвратит неявное преобразование number
, null
или undefined
в boolean
. Например:
if (!!array.length) { /* ... */ }
md5-d563d6246c0e981c16f8a2b3d7f53974
md5-430ec08bab82330fa4e519419e9ad014
However I find the following uses acceptable:
md5-70351fc6fdb328ee060919d6974e2cf4
```tsx
md5-036fd2ddd516eac8e1379cdcb9ac2b9a
Я думаю, это согласуется с тем, что предлагает @marcind .
Я также склонен ослабить проверку LHS для &&, || и операнд!.
@ajafff легализует ли это if (!!array.length)
или if (!possiblyNull)
?
@ajafff @adidahiya есть еще какие-нибудь мысли? Я в той же ситуации, что и @ rhys-vdw.
Беззастенчиво рекламируя собственный проект:
С момента последней работы в этом выпуске я создал свой собственный линтер - проект Fimbullinter . Прочтите документацию для быстрого старта: https://github.com/fimbullinter/wotan/blob/master/packages/wotan/README.md
Он содержит правило no-useless-predicate
, которое может быть тем, что вы ищете. Это комбинация strict-type-predicates
и strict-boolean-expressions
TSLint, но с некоторыми существенными отличиями:
В отличие от TSLint strict-type-predicates
также работает без --strictNullChecks
и правильно обрабатывает параметры типа и типы пустых объектов. (наверное, не так интересно людям, подписавшимся на этот выпуск)
Основное отличие от strict-boolean-expressions
TSLint заключается в том, что он не требует, чтобы все было логическим (он не обнаруживает неявное принуждение). Просто требуется, чтобы каждое условие было правдивым или ложным.
Некоторые примеры:
if (0) {} // error, always falsy
if (1) {} // error, always truthy
declare let array: string[];
if (array.length) {} // no error
if (!array.length) {} // no error
if (!!array.length) {} // no error
if (array.length === undefined) {} // error, condition is always false
if (!!false) {} // 2 errors, because of the double negation of an always falsy value
declare let someString: string;
return someString || 'some default string'; // no error, because 'someString' might be falsy
declare const foo: 'bar' | 'baz';
return foo || 'bas'; // error, 'foo' is always truthy
declare let optionalFunction: (() => void) | undefined;
optionalFunction && optionalFunction(); // no error
Я хотел бы присоединиться к следующему варианту использования из моего фактического кода:
export interface ILoggingRule {
readonly isFinal?: boolean;
readonly loggerNamePattern?: string;
readonly maxLogLevel?: LogLevel;
readonly minLogLevel?: LogLevel;
readonly target: Target;
}
// ...
/**
* Creates an instance of LoggingRule.
* <strong i="6">@param</strong> options Configuration options of the logging rule.
*/
public constructor(options: ILoggingRule) {
// tslint:disable:strict-boolean-expressions
this.isFinal = options.isFinal || false;
this.loggerNamePattern = options.loggerNamePattern || "*";
this.maxLogLevel = options.maxLogLevel || LogLevel.Fatal;
this.minLogLevel = options.minLogLevel || LogLevel.Trace;
this.target = options.target;
// tslint:enable:strict-boolean-expressions
}
Как видите, я использую ||
для обозначения значений по умолчанию, если LHS оказывается неопределенным. Есть ли какой-нибудь краткий способ заставить tslint
понять, что это соответствует strict-boolean-expressions
? В противном случае я вынужден использовать эти команды отключения / включения. (Удивительно, но это проблема только при включенной проверке типов, а не в VSCode.)
Это стандартное, чрезвычайно распространенное и удобное использование в JavaScript, которое определенно не должно приводить к сбою этого правила.
ИМХО, правая часть &&
и ||
не должна проверяться, чтобы допустить короткое замыкание. Это должно быть поведение по умолчанию (или, по крайней мере, должна быть опция типа allow-any-rhs
). В настоящее время я не могу использовать strict-boolean-expressions
, поскольку в нашей кодовой базе много коротких замыканий.
Проверка LHS должна оставаться неизменной ИМХО, поскольку использование string
или number
качестве LHS может быть опасным, см. Этот пример:
function foo(x: string | number | null) {
return x || defaultValue;
}
Это опасно, поскольку многие разработчики не поймут, что не только null
но также 0
и ""
вызовут возврат defaultValue
.
Мне пришлось столкнуться с серьезными ошибками в моем проекте из-за того, что разработчики не приняли во внимание, что ""
и 0
также являются ложными. Предотвращение такого кода - мой основной вариант использования strict-boolean-expressions
.
Исправлено в https://github.com/palantir/tslint/pull/4159, просто нужен отзыв от соавтора.
Упс, просто хотел уточнить, что один из моих примеров был плохим:
const x = possiblyUndefined || 5;
Это не должно работать, потому что possiblyUndefined
может быть 0
что может быть логической ошибкой. Похоже, здесь сработает пиар
include for array - это функция ES7.
Вам необходимо изменить конфигурацию ts, чтобы использовать ES7 или ESNEXT 🦄
С уважением, 🚀
@rimiti Привет, я не могу понять, о чем вы говорите, вы уверены, что разместили этот комментарий в правильной теме?
@dobesv Ой, ты прав, прости;)
исправлено # 4159, будет доступно в следующем выпуске
Самый полезный комментарий
На мой взгляд,
strict-boolean-expressions
должен проверять только левый операнд&&
и||
. Эти операторы (по сути) являются сахаром для троичных:a && b
равноa ? b : a
, аa || b
равноa ? a : b
. Когда вы думаете об этом в этих терминах, игнорирование RHS имеет большой смысл, и это приведет к тому, что поведение короткозамкнутых операторов будет соответствовать поведению троичных.Затем , если все это находится внутри if / for / while,
strict-boolean-conditions
может вступить в игру и проверить общее выражение. Я думаю, что это охватит все полезные случаи, и я смогу снова включить это правило.Код, который пометил это как проблему для меня, был документированным общим шаблоном React :
@ajafff Его код не проходит для меня
Намерение выражения является условным для LHS, поэтому мое предложение игнорировать RHS также решило бы его проблему.