Jenis cek kelas di TypeScript

240

Dalam ActionScript, dimungkinkan untuk memeriksa jenis pada saat dijalankan menggunakan operator is :

var mySprite:Sprite = new Sprite(); 
trace(mySprite is Sprite); // true 
trace(mySprite is DisplayObject);// true 
trace(mySprite is IEventDispatcher); // true

Apakah mungkin untuk mendeteksi jika suatu variabel (extends atau) adalah kelas atau antarmuka tertentu dengan TypeScript?

Saya tidak dapat menemukan apa pun tentang itu dalam spesifikasi bahasa. Itu harus ada ketika bekerja dengan kelas / antarmuka.

Mark Knol
sumber

Jawaban:

319

4.19.4 Instansi operator

The instanceofOperator membutuhkan operan kiri menjadi tipe Setiap, jenis objek, atau jenis jenis parameter, dan operan yang tepat untuk menjadi tipe Setiap atau subtipe dari 'Fungsi' jenis antarmuka. Hasilnya selalu dari tipe primitif Boolean.

Jadi bisa digunakan

mySprite instanceof Sprite;

Perhatikan bahwa operator ini juga ada dalam ActionScript tetapi tidak boleh digunakan lagi di sana:

Operator is, yang baru untuk ActionScript 3.0, memungkinkan Anda untuk menguji apakah suatu variabel atau ekspresi adalah anggota dari tipe data yang diberikan. Dalam versi sebelumnya dari ActionScript, instanceof operator menyediakan fungsionalitas ini, tetapi dalam ActionScript 3.0 instanceof operator tidak boleh digunakan untuk menguji keanggotaan tipe data. Operator is harus digunakan sebagai ganti instanceof operator untuk memeriksa tipe manual, karena ekspresi x instanceof y hanya memeriksa rantai prototipe x untuk keberadaan y (dan dalam ActionScript 3.0, rantai prototipe tidak memberikan gambaran lengkap tentang hierarki warisan).

TypeScript instanceofberbagi masalah yang sama. Karena bahasa ini masih dalam pengembangan, saya sarankan Anda untuk menyatakan proposal fasilitas tersebut.

Lihat juga:

Zeta
sumber
54

TypeScript memiliki cara untuk memvalidasi tipe variabel dalam runtime. Anda dapat menambahkan fungsi validasi yang mengembalikan predikat tipe . Jadi, Anda bisa memanggil fungsi ini di dalam pernyataan if, dan pastikan bahwa semua kode di dalam blok itu aman digunakan sebagai tipe yang Anda pikir.

Contoh dari dokumen TypeScript:

function isFish(pet: Fish | Bird): pet is Fish {
   return (<Fish>pet).swim !== undefined;
}

// Both calls to 'swim' and 'fly' are now okay.
if (isFish(pet)) {
  pet.swim();
}
else {
  pet.fly();
}

Lihat lebih lanjut di: https://www.typescriptlang.org/docs/handbook/advanced-types.html

Gilad S
sumber
29
Ini bukan typechecking runtime, itu hanya memeriksa apakah suatu objek memiliki properti tertentu. Ini mungkin bagus untuk tipe-tipe union, jadi cocok untuk case khusus ini, tetapi tidak benar-benar bisa membuat "isThingy" untuk semua seperti ini. Juga jika ikan dan burung bisa berenang, Anda akan hancur. Saya senang saya menggunakan Haxe yang memiliki pengecekan tipe yang andal sehingga Anda dapat melakukannya Std.is(pet, Fish), yang bekerja pada tipe, antarmuka, dll.
Mark Knol
4
Saya menemukan jawaban ini bermanfaat, tetapi saya pikir Anda bisa mengubah sedikit lebih tepat. Itu isFishsendiri adalah predikat yang dibuat, dan tubuhnya tidak harus menjadi predikat satu-baris. Keuntungan dari hal ini adalah bahwa kompiler memahami pada waktu kompilasi fungsi-fungsi yang sesuai yang mungkin, tetapi kode Anda di dalam isFishdieksekusi saat runtime. Anda bahkan bisa membuat penjaga berisi instanceofpernyataan, misalnya return pet instanceof Fish(dengan asumsi itu kelas dan bukan antarmuka), tetapi ini tidak perlu karena kompiler mengerti instanceofsecara langsung.
4
ini juga disebut "Penjaga Tipe yang Ditetapkan Pengguna", lihat basarat.gitbooks.io/typescript/content/docs/types/…
Julian
@ MarkKnol itu sebenarnya adalah pengecekan runtime tetapi membawa pada jenis naskah kemampuan untuk memahami jenis yang disimpulkan juga (artinya: Anda dapat mempercayai saya ini akan menjadi tipe X atau Y karena saya akan mengujinya saat runtime).
Flavien Volken
3
Anda mungkin ingin mempertimbangkan untuk menggunakan (pet as Fish)karena tslinter akan mengeluh (<Fish>pet). Lihat tslint doc
Bryan
1

Anda dapat menggunakan instanceofoperator untuk ini. Dari MDN:

Turunan dari operator menguji apakah properti prototipe konstruktor muncul di mana saja di rantai prototipe objek.

Jika Anda tidak tahu apa prototipe dan rantai prototipe saya sangat merekomendasikan mencarinya. Juga di sini adalah contoh JS (TS bekerja serupa dalam hal ini) yang mungkin menjelaskan konsep:

    class Animal {
        name;
    
        constructor(name) {
            this.name = name;
        }
    }
    
    const animal = new Animal('fluffy');
    
    // true because Animal in on the prototype chain of animal
    console.log(animal instanceof Animal); // true
    // Proof that Animal is on the prototype chain
    console.log(Object.getPrototypeOf(animal) === Animal.prototype); // true
    
    // true because Object in on the prototype chain of animal
    console.log(animal instanceof Object); 
    // Proof that Object is on the prototype chain
    console.log(Object.getPrototypeOf(Animal.prototype) === Object.prototype); // true
    
    console.log(animal instanceof Function); // false, Function not on prototype chain
    
    

Rantai prototipe dalam contoh ini adalah:

animal> Animal.prototype> Object.prototype

Willem van der Veen
sumber