Tslint: 'tidak ada tipe yang dapat disimpulkan' dan aturan 'typedef' bertentangan

Dibuat pada 3 Okt 2015  ·  33Komentar  ·  Sumber: palantir/tslint

Halo lagi,

Saya tidak yakin apakah ini masalah atau keputusan desain, tetapi saya dapat melihat konflik antara aturan no-inferrebale-types dan typedef .

Mantan.

function fn(): void {
    for (let i = 0; i < 100; i++) {
        console.log(i);
    }
}

Cuplikan dari https://github.com/palantir/tslint/blob/master/docs/sample.tslint.json :

 "typedef": [true, ...],
 "no-inferrable-types": true,

Ketika saya mengaktifkan dua aturan ini, saya mendapatkan:

error (typedef) test.ts[2, 12]: expected variable-declaration: 'i' to have a typedef

Menambahkan anotasi jenis number ke variabel i menyebabkan kesalahan berikut pada gilirannya:

error (no-inferrable-types) test.ts[2, 14]: LHS type (number) inferred by RHS expression, remove type annotation

Apakah ada cara agar kedua aturan ini hidup berdampingan?

Sebagai contoh, saya ingin memiliki variabel inferrable yang dideklarasikan secara langsung dengan tipe primitif (seperti yang dikatakan oleh dokumen aturan: number , boolean atau string ), tetapi di sisi lain, saya ingin untuk memaksa typedefs pada tipe non-primitif.

Terima kasih,

HAI.

P1 Enhancement 🌹 R.I.P. 🌹

Komentar yang paling membantu

:+1: Idealnya (imo) Saya ingin cara untuk mengatakan "selalu membutuhkan typedef, kecuali jenisnya tidak dapat disimpulkan". Yang menurut saya tidak mungkin sekarang.

Semua 33 komentar

Tangkapan yang bagus, terima kasih atas perhatiannya. Saya menambahkan aturan no-inferrable-types tanpa memikirkan bagaimana aturan itu bisa bertentangan dengan aturan typedef , wah! Untuk saat ini saya sarankan untuk mematikan salah satu dari keduanya, atau hanya menggunakan beberapa opsi dari aturan typedef .

Untuk jangka panjang, saya pikir kita akan ingin mengintegrasikan no-inferrable-types ke dalam aturan typedef atau setidaknya kita ingin TSLint mendeteksi konfigurasi yang bertentangan seperti mengaktifkan kedua aturan.

Saya menghadapi masalah yang sama.
Saya telah mematikan tipe yang tidak dapat disimpulkan untuk saat ini.

Ya sama di sini, saya ingin memiliki kemampuan untuk memiliki kedua aturan itu hidup berdampingan.
Saya tidak ingin aturan typedef muncul jika tipe variabel dapat disimpulkan.
yaitu "tipe yang tidak dapat disimpulkan" harus diprioritaskan daripada "typedef"

+1

let id: number = 0;
for (let job: string of NAMES_PROFFESSIONS) {
     /** some code */
     id++;
}

(tipe tidak dapat disimpulkan) Tipe LHS (angka) disimpulkan oleh ekspresi RHS, hapus anotasi tipe

+1

Apakah definisi Anda tentang tipe "tidak dapat disimpulkan" termasuk tugas konstruktor?

// BAD (this hurts my eyes to read)
let labels: Map<string, string> = new Map<string, string>();
// GOOD (type is obvious)
let labels = new Map<string, string>();

tetapi juga...

// BAD (in a diff, it's not obvious what this type is)
let labels = this.buildLabels();
// GOOD
let labels: Map<string, string> = this.buildLabels();

Ya, itu berbahaya. Jika saya ingin menyederhanakan kode saya dan mencegah penggunaan deklarasi tipe untuk variabel yang diinisialisasi secara langsung, saya tidak dapat melakukan ini secara ketat dan ini membawa ke hal seperti itu:

let x = 2;
let y;
let z: number;

x = 1;
y = 1;
z = 1;
x = 's'; // Type 'string' is not assignable to type 'number'
y = 's'; // It's OK
z = 's'; // Type 'string' is not assignable to type 'number'

Ini mungkin opsi yang sangat berguna untuk mengizinkan deklarasi tipe lewati hanya untuk variabel yang diinisialisasi.

… dan benar-benar tidak hanya untuk tipe primitif, seperti yang dikatakan @pgonzal !
Lihat ini, ini mengerikan:

const onChange: () => void = () => this.update();

:+1: Idealnya (imo) Saya ingin cara untuk mengatakan "selalu membutuhkan typedef, kecuali jenisnya tidak dapat disimpulkan". Yang menurut saya tidak mungkin sekarang.

Saya mengalami ini dan membuat flag ignore-params yang membantu dalam kasus saya. Saya ingin memaksa typedefs untuk semua parameter metode/fungsi bahkan ketika mereka dapat dengan mudah disimpulkan.

Lihat PR: #1190 jika Anda ingin mencobanya

Sudah lama sejak masalah asli diajukan. Apakah opsi rekomendasi pada saat ini untuk menonaktifkan no-inferrable-types dan menyertakan tipe pada semuanya? Hal lain untuk mencoba dan mengaktifkan dan menggabungkan no-inferrable-types dan typedef tampaknya seperti peretasan dan menghasilkan banyak peringatan yang tidak berguna. Berharap untuk solusi yang lebih baik dalam waktu dekat.

@corydeppen Perhatikan 8 jempol atas saran @englercj , di atas. Tidak jelas apa arti "gabungkan" dalam komentar "sepertinya seperti peretasan". Jika maksud Anda "gunakan bersama dalam tslint.json , maka, ya. Tapi "menggabungkan" argumen optional-inferrable-types pada typedef akan bagus (setidaknya, untuk 9 orang dari kita).

Bisakah kami mendapatkan pembaruan tentang ini, tolong?

Saya pikir cara terbaik untuk menangani ini adalah dengan menghentikan no-inferrable-types dan hanya meneruskan objek opsi ke typedef untuk mengabaikan kurangnya definisi tipe jika tipenya dapat disimpulkan menurut pola tertentu, seperti initialized , initialized primitives , call signatures dan pola-pola lain yang akan memenuhi kebutuhan kita sebagai pengembang.

Bagi saya ini lebih masuk akal, karena harus selalu ada typedef, kecuali ada sesuatu yang memberi tahu Anda apa jenis fungsinya. Dan itu akan dapat dikonfigurasi juga, karena, mungkin kita ingin properties yang diinisialisasi di kelas memiliki tipe yang dapat disimpulkan, tetapi tidak untuk call signatures misalnya.

Akan sangat bagus jika seseorang dapat membantu untuk memperbaikinya. Sampai saat itu, kami dipaksa untuk memilih antara "deklarasi tipe tidak cukup untuk dapat dibaca" versus "berantakan dengan terlalu banyak deklarasi tipe".

Masalah ini telah terbuka sejak 3 Oktober 2015 -- sejak saat itu, tim saya telah menulis sekitar 2000 file sumber TypeScript yang semuanya berantakan dengan terlalu banyak deklarasi tipe.

typedef menerima konfigurasi. Jadi mungkin hanya konfigurasi lain saja untuk mengabaikan definisi tipe jika tipenya tidak dapat disimpulkan, artinya

Cukup ketik di mana pun tidak sedang diinisialisasi.

Sepertinya karena tidak ada konsensus yang jelas tentang bagaimana menangani masalah ini, tidak ada kemajuan yang dibuat. Contoh komentar: https://github.com/theia-ide/theia/issues/356#issuecomment -319350833

Saya kira kita semua setuju bahwa solusi apa pun lebih baik daripada membiarkan segala sesuatunya apa adanya. Jika menurut Anda ada perubahan pada status-quo sehubungan dengan masalah ini adalah baik, silakan 👍 komentar ini. Jika Anda cukup berpengetahuan untuk membuat PR untuk memperbaiki masalah ini, tolong bantu kami semua ❤️ .

Akan menerima PR untuk:

  • tambahkan opsi ke typedef yang memungkinkannya mengabaikan kasus di mana no-inferrable-types mengatakan untuk tidak memberikan tipe

Typedef menerima konfigurasi. Jadi mungkin hanya konfigurasi lain untuk mengabaikan definisi tipe jika tipenya tidak dapat disimpulkan, artinya 'Ketik saja di mana pun tidak sedang diinisialisasi.'

Aturan typedef adalah untuk orang yang suka memiliki definisi tipe eksplisit dalam basis kode mereka. Jika Anda menginginkan perilaku di atas untuk "ketik saja di mana pun tidak sedang diinisialisasi", Anda lebih baik menonaktifkan typedef dan memastikan Anda mengaktifkan noImplictAny sebagai opsi kompiler TypeScript.

Ada juga kasus rumit di mana beberapa hal yang diinisialisasi memerlukan typedef, seperti dalam cuplikan berikut:

interface Literal {
    field: "value"
}

const literal0 = {
    field: "value",
};
const literal1: Literal = {
    field: "value",
};

const func = (obj: Literal) => { };
func(literal0);  // Error! Type 'string' is not assignable to type '"value"'.
func(literal1);

Juga, sementara kami memperbaikinya, ingin menyebutkan bahwa kemungkinan ada beberapa aturan pihak ketiga yang hebat di luar sana, seperti no-unnecessary-type-annotation (https://github.com/ajafff/tslint-consistent-codestyle/blob/ master/docs/no-unnecessary-type-annotation.md) misalnya. Jika ada yang mengetahui aturan pihak ketiga lainnya yang memberikan perilaku yang diinginkan, harap posting di sini dan kami dapat secara resmi merekomendasikannya atau mengadopsinya ke dalam inti jika masuk akal.

@JKillian terima kasih atas rekomendasinya, saya pikir itulah yang sebenarnya saya inginkan. Ada posting yang sangat bagus tentang menghindari tipe any : Jangan gunakan "naked any", buat "antarmuka apa saja".

Tentang:

interface Literal {
    field: "value"
}

const literal0 = {
    field: "value",
};
const literal1: Literal = {
    field: "value",
};

const func = (obj: Literal) => { };
func(literal0);  // Error! Type 'string' is not assignable to type '"value"'.
func(literal1);

Saya tidak melihat bagaimana ini bisa menjadi perilaku yang tidak diinginkan atau kasus yang rumit. Anda ingin memastikan bahwa obj memiliki properti field dengan nilai value , dan bahkan ketika Anda menginisialisasi literal0 dengan properti yang tampak seperti kendala , Anda dapat memodifikasinya ke string lain.

Saya tahu ini bukan kasus penggunaan yang baik, tetapi sebagian besar kasus ketika Anda menggunakan literal, Anda mungkin menginginkan literal itu, bukan primitif.

Saya memiliki konfigurasi berikut:
json "no-inferrable-types": true, "typedef": [true, "call-signature", "parameter"],
Dan kode ini:
javascript private static readonly DEVICE_UID: string = 'device_uid'; private static readonly DEVICE_PLATFORM: string = 'browser'; private static readonly AGENT_DEFAULT_ICON = 'http://localhost:3000/icon.png';

Mengapa saya tidak mendapatkan kesalahan dalam dua deklarasi pertama?

@sandrocsimas Menarik, tapi di luar topik menurut saya; AFAICT masalah itu tidak terkait dengan masalah ini. Saya sarankan Anda memulai masalah lain (fwiw!).

@estaub , ya saya akan. Saya mendapatkan perilaku yang sama bahkan tanpa aturan typedef.

@sandrocsimas itu karena ini adalah properti readonly, dan TypeScript semacam itu menyimpulkan tipenya sebagai literal. Mengetiknya sebagai string Anda memberi tahu bahwa itu harus memiliki string, itu tidak harus memiliki nilai literal itu dan nilainya tidak boleh berubah secara statis.

Akan menyenangkan untuk memiliki aturan 'require-typedef-except-inferrable'.

@FiretronP75 seperti yang dikatakan @JKillian , itu hanya opsi noImplicitAny dari TSC.

@michaeljota terima kasih, saya tidak menyadari opsi noImplicitAny dari kompiler memberikan pengecualian untuk inferrable. Akan tetap menyenangkan untuk memiliki di tslint, untuk opsi menjadikannya peringatan alih-alih merusak kompilasi, dan untuk memiliki flag komentar tslint.

Saya mengerti mengapa ini menjadi sesuatu yang diinginkan, tetapi dengan no-unused-variables sebagai contoh, saya tidak berpikir kasus penggunaan yang dicakup oleh TSC akan didukung oleh tim TSLint. Saya tahu itu tidak sama dengan _linter error_ daripada _compiler error_ tetapi pada akhirnya, keduanya tentang menulis kode yang lebih baik. Sekarang hari dengan solusi sebagai Webpack atau Parcel yang memungkinkan Anda untuk mengkompilasi dan menjalankan kode bahkan dengan kesalahan TSC, saya tidak melihat ini sebagai masalah nyata.

Apakah ini sudah diperbaiki di versi terbaru?

Saya masih tidak berpikir ini ada di peta jalan. Anda harus mempertimbangkan untuk menggunakan noImplicitAny dari TSC

Waktunya TSLint telah tiba!

TSLint tidak lagi menerima sebagian besar permintaan fitur per #4534. Lihat TypeScript-eslint.io untuk cara baru yang mengkilap untuk lint kode TypeScript Anda dengan ESLint . ✨.

Sangat menyenangkan membuka sumber dengan Anda semua!

Bunyi bip! TSLint tidak digunakan lagi _(#4534)_ dan Anda harus beralih ke TypeScript-eslint ! 🤖.

Masalah ini sedang dikunci untuk mencegah diskusi lebih lanjut yang tidak perlu. Terima kasih! 👋.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

jacob-robertson picture jacob-robertson  ·  3Komentar

ghost picture ghost  ·  3Komentar

dashmug picture dashmug  ·  3Komentar

avanderhoorn picture avanderhoorn  ·  3Komentar

zewa666 picture zewa666  ·  3Komentar