Sprawdzanie typu klasy w TypeScript

240

W języku ActionScript można sprawdzić typ w czasie wykonywania za pomocą operatora is :

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

Czy można wykryć, czy zmienna (rozszerzenie lub) jest określoną klasą lub interfejsem za pomocą TypeScript?

Nie mogłem znaleźć nic na ten temat w specyfikacjach językowych. Powinien być obecny podczas pracy z klasami / interfejsami.

Mark Knol
źródło

Odpowiedzi:

318

4.19.4 Operator instanceof

instanceofOperatora wymaga lewy argument być typu każdy, typ obiektu lub typu parametru typu, a odpowiedni argument być dowolnego typu lub podtypu „funkcja” typu interfejsu. Wynik jest zawsze typu logicznego typu pierwotnego.

Więc możesz użyć

mySprite instanceof Sprite;

Pamiętaj, że ten operator jest również w języku ActionScript, ale nie należy go już tam używać:

Operator is, który jest nowością w języku ActionScript 3.0, pozwala przetestować, czy zmienna lub wyrażenie należy do danego typu danych. W poprzednich wersjach ActionScript operator instanceof zapewniał tę funkcjonalność, ale w ActionScript 3.0 operator instanceof nie powinien być wykorzystywany do testowania członkostwa w typach danych. Do ręcznego sprawdzania typu należy użyć operatora is zamiast operatora instanceof, ponieważ wyrażenie x instanceof y sprawdza jedynie łańcuch prototypowy x pod kątem istnienia y (aw ActionScript 3.0 łańcuch prototypowy nie zapewnia pełnego obrazu hierarchia dziedziczenia).

TypeScript ma instanceofte same problemy. Ponieważ jest to język, który wciąż się rozwija, polecam przedstawić propozycję takiego rozwiązania.

Zobacz też:

Zeta
źródło
54

TypeScript ma sposób sprawdzania poprawności typu zmiennej w czasie wykonywania. Możesz dodać funkcję sprawdzania poprawności, która zwraca predykat typu . Możesz więc wywołać tę funkcję w instrukcji if i upewnić się, że cały kod w tym bloku jest bezpieczny w użyciu, tak jak myślisz.

Przykład z dokumentów 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();
}

Zobacz więcej na: https://www.typescriptlang.org/docs/handbook/advanced-types.html

Gilad S.
źródło
29
Nie jest to sprawdzanie typu środowiska wykonawczego, a jedynie sprawdzanie, czy obiekt ma określoną właściwość. Może to być przydatne dla typów unii, więc działa w tym konkretnym przypadku, ale tak naprawdę nie jest możliwe utworzenie „isThingy” dla wszystkiego takiego. Również jeśli zarówno ryby, jak i ptaki mogą pływać, jesteś skazany na zagładę. Cieszę się, że korzystam z Haxe, który ma niezawodne sprawdzanie typów, dzięki czemu możesz to zrobić Std.is(pet, Fish), który działa na typach, interfejsach itp.
Mark Knol
4
Uznałem tę odpowiedź za pomocną, ale myślę, że można ją nieco poprawić. isFishSama jest orzecznikiem, który jest tworzony, a jego ciało nie musi być orzecznikiem jeden-liner. Zaletą tego jest to, że kompilator rozumie w czasie kompilacji odpowiednie możliwe funkcje, ale kod wewnątrz isFishjest wykonywany w czasie wykonywania. Możesz nawet mieć wartownik zawierający instanceofinstrukcję, np. return pet instanceof Fish(Zakładając, że jest to klasa, a nie interfejs), ale byłoby to niepotrzebne, ponieważ kompilator rozumie instanceofbezpośrednio.
4
nazywa się to również „Definiowanymi przez użytkownika typami
Julian
@ MarkKnol tak naprawdę sprawdza środowisko uruchomieniowe, ale daje maszynie do zrozumienia również wywnioskowany typ (co oznacza: możesz mi zaufać, że będzie to typ X lub Y, ponieważ przetestuję go w czasie wykonywania).
Flavien Volken
3
Możesz rozważyć użycie, (pet as Fish)ponieważ tslinter narzeka (<Fish>pet). Zobacz tslint doc
Bryan,
1

Możesz do tego użyć instanceofoperatora. Z MDN:

Operator instanceof sprawdza, czy właściwość prototypowa konstruktora pojawia się w dowolnym miejscu łańcucha prototypowego obiektu.

Jeśli nie wiesz, jakie są prototypy i łańcuchy prototypów, bardzo polecam poszukać ich. Oto także przykład JS (TS działa pod tym względem w podobny sposób), który może wyjaśnić pojęcie:

    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
    
    

Łańcuch prototypów w tym przykładzie to:

animal> Animal.prototype> Object.prototype

Willem van der Veen
źródło