Tslint: ekspresi boolean ketat tidak boleh diaktifkan untuk operator logika yang digunakan dalam konteks non-boolean

Dibuat pada 4 Okt 2017  ·  18Komentar  ·  Sumber: palantir/tslint

Laporan Bug

  • __TSLint versi__: 5.7
  • __TypeScript versi__: 2.5.3
  • __Menjalankan TSLint melalui__: CLI

Kode TypeScript sedang dilinting

// code snippet
function valueOrDefault(a?: string) {
  return a || "the default";
}

dengan konfigurasi tslint.json :

{
  "defaultSeverity": "error",
  "extends": [
      "tslint:all"
  ]
}

Perilaku sebenarnya

Mendapatkan laporan dari 2 kesalahan:
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.

Perilaku yang diharapkan

Tidak ada kesalahan yang dilaporkan. Saya menggunakan operator || logis untuk memberikan nilai default untuk parameter (saya tahu saya bisa menggunakan deklarasi default parameter fungsi, cuplikan hanya untuk menggambarkan masalah umum). Tidak ada boolean dimainkan di mana pun: baik input maupun output dari ekspresi.

Fixed Bug

Komentar yang paling membantu

Menurut pendapat saya, strict-boolean-expressions seharusnya hanya memeriksa operan kiri && dan || . Operator tersebut (pada dasarnya) adalah gula untuk ternaries: a && b sama dengan a ? b : a , dan a || b sama dengan a ? a : b . Ketika Anda memikirkannya dalam istilah itu, mengabaikan RHS sangat masuk akal, dan itu akan membawa perilaku untuk operator hubung singkat sejalan dengan perilaku untuk ternaries.

Kemudian , jika semuanya ada di dalam if/for/while, strict-boolean-conditions bisa ikut bermain dan memeriksa ekspresi keseluruhan . Saya pikir ini akan mencakup semua kasus yang berguna, dan saya dapat mengaktifkan kembali aturan ini.

Kode yang menandai ini sebagai masalah bagi saya adalah pola React umum yang terdokumentasi ini:

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 ​​Kodenya tidak lulus linter untuk saya, bahkan dengan semua opsi aturan diaktifkan, karena RHS konstan:

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.

Maksud dari ekspresi itu adalah persyaratan pada LHS, jadi usulan saya untuk mengabaikan RHS akan menyelesaikan masalahnya juga.

Semua 18 komentar

Pikiran? Doa? Saran di mana/bagaimana memulainya?

@marcind dapatkah Anda memberikan contoh bagaimana seharusnya berperilaku berbeda dari pergantian aturan?

Maaf, bagian mana pengajuan awal saya yang tidak jelas?

Saya kira maksud saya adalah bahwa aturan ini hanya boleh berjalan dalam "konteks boolean", saya dapat memikirkan dua kasus:

  1. Digunakan dalam if , while , atau for
  2. Ditetapkan ke variabel yang diketik sebagai boolean .

Aturan tidak boleh berjalan ketika saya mencoba memberikan nilai default atau evaluasi hubung singkat

  1. const a: string = potentiallyUndefinedString || "the default";
  2. const a: string | undefined = potentiallyUndefinedObject && potentiallyUndefinedObject.getString()

@marcind contoh dari posting terakhir Anda akan berfungsi jika Anda menggunakan opsi "allow-undefined-union" .

Bagian lain dari permintaan Anda harus berupa aturan terpisah bernama strict-boolean-conditions yang hanya memeriksa if , for , while , do ... while dan kondisional ekspresi ( x ? y : z ).
Saya bisa membayangkan itu hanya akan memeriksa jenis seluruh kondisi dan bukan konstituennya:

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
}

Mungkin ini bisa menjadi pilihan untuk aturan yang ada daripada aturan baru...

Menurut pendapat saya, strict-boolean-expressions seharusnya hanya memeriksa operan kiri && dan || . Operator tersebut (pada dasarnya) adalah gula untuk ternaries: a && b sama dengan a ? b : a , dan a || b sama dengan a ? a : b . Ketika Anda memikirkannya dalam istilah itu, mengabaikan RHS sangat masuk akal, dan itu akan membawa perilaku untuk operator hubung singkat sejalan dengan perilaku untuk ternaries.

Kemudian , jika semuanya ada di dalam if/for/while, strict-boolean-conditions bisa ikut bermain dan memeriksa ekspresi keseluruhan . Saya pikir ini akan mencakup semua kasus yang berguna, dan saya dapat mengaktifkan kembali aturan ini.

Kode yang menandai ini sebagai masalah bagi saya adalah pola React umum yang terdokumentasi ini:

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 ​​Kodenya tidak lulus linter untuk saya, bahkan dengan semua opsi aturan diaktifkan, karena RHS konstan:

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.

Maksud dari ekspresi itu adalah persyaratan pada LHS, jadi usulan saya untuk mengabaikan RHS akan menyelesaikan masalahnya juga.

Saya setuju bahwa memeriksa RHS && dan || adalah bug.


Saya juga cenderung melonggarkan pemeriksaan untuk LHS && , || dan operan ! . Ini hanya boleh diperiksa apakah ekspresi selalu benar atau selalu salah.
Itu hanya menyisakan kondisi if , for , while , do ... while dan ekspresi kondisional untuk pemeriksaan ketat untuk mengizinkan hanya boolean (atau apa pun yang dikonfigurasi ). Pikiran @adidahiya?

Saat ini mengaktifkan aturan ini dengan opsi konfigurasi yang tersedia akan memerlukan hari kerja dengan basis kode kami. :(

Saya mengaktifkannya dengan harapan akan mencegah konversi implisit number , null atau undefined menjadi boolean . Sebagai contoh:

if (!!array.length) { /* ... */ }


md5-d563d6246c0e981c16f8a2b3d7f53974





md5-430ec08bab82330fa4e519419e9ad014




However I find the following uses acceptable:



md5-70351fc6fdb328ee060919d6974e2cf4



```tsx


md5-036fd2ddd516eac8e1379cdcb9ac2b9a


Saya pikir ini setuju dengan apa yang disarankan @marcind .

Saya juga cenderung melonggarkan pemeriksaan LHS &&, || dan operan dari !.

@ajafff apakah ini akan melegalkan if (!!array.length) atau if (!possiblyNull) ?

@ajafff @adidahiya ada pemikiran lebih lanjut di sini? Saya berada dalam situasi yang sama persis dengan @rhys-vdw.

Tanpa malu-malu mengiklankan proyek saya sendiri:
Sejak aktivitas terakhir saya dalam edisi ini, saya membuat linter saya sendiri, proyek Fimbullinter . Baca dokumen untuk memulai cepat: https://github.com/fimbullinter/wotan/blob/master/packages/wotan/README.md

Ini berisi aturan no-useless-predicate , yang mungkin Anda cari. Ini adalah kombinasi dari strict-type-predicates dan strict-boolean-expressions TSLint, tetapi dengan beberapa perbedaan utama:

Berbeda dengan strict-type-predicates TSLint juga berfungsi tanpa --strictNullChecks dan menangani parameter tipe dan tipe objek kosong dengan benar. (mungkin tidak begitu menarik bagi orang-orang yang berlangganan masalah ini)
Perbedaan utama dengan strict-boolean-expressions TSLint adalah bahwa ia tidak mengharuskan semuanya menjadi boolean (tidak mendeteksi paksaan implisit). Itu hanya membutuhkan setiap kondisi untuk menjadi mungkin benar dan salah.

Beberapa contoh:

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

Saya ingin mengikuti kasus penggunaan berikut dari kode saya yang sebenarnya:

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
}

Seperti yang Anda lihat, saya menggunakan || untuk menunjukkan nilai default jika LHS tidak terdefinisi. Apakah ada cara ringkas yang membuat tslint mengerti bahwa ini mematuhi strict-boolean-expressions ? Kalau tidak, saya terpaksa menggunakan perintah nonaktifkan/aktifkan itu. (Anehnya ini hanya masalah dengan pemeriksaan tipe diaktifkan dan tidak di VSCode.)

Penggunaan ini standar dan sangat umum dan nyaman dalam JavaScript, dan seharusnya tidak memicu kegagalan aturan ini.

IMHO RHS && dan || tidak boleh diperiksa, untuk memungkinkan hubungan arus pendek. Ini harus menjadi perilaku default (atau setidaknya harus ada opsi seperti allow-any-rhs ). Saat ini, saya tidak dapat menggunakan strict-boolean-expressions , karena ada banyak hubungan pendek di basis kode kami.

Memeriksa LHS harus tetap apa adanya IMHO, karena menggunakan string atau number sebagai LHS bisa berbahaya, lihat contoh ini:

function foo(x: string | number | null) {
  return x || defaultValue;
}

Ini berbahaya karena banyak pengembang akan gagal untuk memahami bahwa tidak hanya null tetapi juga 0 dan "" akan menyebabkan defaultValue dikembalikan.

Saya harus berurusan dengan bug utama dalam proyek saya, karena pengembang gagal mempertimbangkan bahwa "" dan 0 juga salah. Mencegah kode semacam ini, adalah kasus penggunaan utama saya untuk strict-boolean-expressions .

Diperbaiki di https://github.com/palantir/tslint/pull/4159 hanya perlu review dari kolaborator.

Ups, hanya ingin mengklarifikasi bahwa salah satu contoh saya buruk:

const x = possiblyUndefined || 5;

Itu seharusnya tidak berfungsi karena possiblyUndefined mungkin 0 yang bisa menjadi kesalahan logika. Sepertinya PR @dobesv akan berfungsi di sini.

termasuk untuk array adalah fitur ES7.
Anda perlu mengubah konfigurasi ts Anda untuk menggunakan ES7 atau ESNEXT

Salam,

@rimiti Hai, saya tidak tahu apa yang Anda maksud, apakah Anda yakin Anda memposting komentar itu di utas yang benar?

@dobesv Oh, Anda benar, maaf;)

diperbaiki oleh #4159, akan tersedia di rilis berikutnya

Apakah halaman ini membantu?
0 / 5 - 0 peringkat