Перевірка типу класу в TypeScript


240

У ActionScript можна перевірити тип під час виконання за допомогою оператора is :

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

Чи можливо виявити, чи змінна (розширюється чи) є певним класом або інтерфейсом з TypeScript?

Я нічого не міг знайти про це в мовних специфікаціях. Він повинен бути там під час роботи з класами / інтерфейсами.

Відповіді:


318

4.19.4 Примірник оператора

instanceofОператор вимагає лівого операнда бути типу Будь-якими, типу об'єкта, або типу параметра типу, а правий операнда , щоб мати типу будь-яких або підтип «Function» типу інтерфейсу. В результаті завжди булевий примітивний тип.

Таким чином, ви можете використовувати

mySprite instanceof Sprite;

Зауважте, що цей оператор також є у ActionScript, але його там більше не слід використовувати:

Оператор is, який є новим для ActionScript 3.0, дозволяє перевірити, чи є змінна або вираз членом даного типу даних. У попередніх версіях ActionScript оператор instanceof забезпечував цю функціональність, але в ActionScript 3.0 оператор instanceof не повинен використовуватися для тестування на приналежність до даних. Оператор is повинен використовуватись замість оператора instanceof для ручної перевірки типу, оскільки вираз x instanceof y просто перевіряє ланцюг прототипу x на наявність y (а в ActionScript 3.0 ланцюг прототипу не забезпечує повного уявлення про ієрархія спадщини).

TypeScript instanceofподіляє ті самі проблеми. Оскільки це мова, яка ще розвивається, я рекомендую вам висловити пропозицію щодо такої програми.

Дивитися також:


54

TypeScript має спосіб перевірити тип змінної під час виконання. Ви можете додати функцію перевірки, яка повертає предикат типу . Таким чином, ви можете викликати цю функцію всередині оператора if і бути впевненим, що весь код у цьому блоці безпечно використовувати як тип, який ви вважаєте, що це.

Приклад документів 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();
}

Детальніше дивіться на веб- сайті: https://www.typescriptlang.org/docs/handbook/advanced-types.html


29
Це не перевірка набору тексту виконання, це лише перевірка наявності об'єкта певної властивості. Це може бути приємно для типів об'єднання, тому працює в цьому конкретному випадку, але створити "isThingy" для всього подібного не можна. Також якщо риба і птах могли плавати, ви приречені. Я радий, що я використовую Haxe, який має надійну перевірку типу, щоб ви могли це робити Std.is(pet, Fish), яка працює на типи, інтерфейси тощо.
Марк Кнол

4
Я вважаю цю відповідь корисною, але я думаю, ви можете її налаштувати трохи точніше. Сам isFishпо собі є присудком, який створюється, і його тіло не повинно бути односкладним предикатом. Перевага цього полягає в тому, що компілятор розуміє під час компіляції відповідні можливі функції, але ваш код всередині isFishвиконується під час виконання. Ви навіть можете охоронець містити instanceofзаяву, наприклад return pet instanceof Fish(якщо припустити, що це клас, а не інтерфейс), але це було б зайвим, оскільки компілятор розуміє це instanceofбезпосередньо.

4
це також називається "Охоронці, визначені користувачем", див. basarat.gitbooks.io/typescript/content/docs/types/…
Джуліан

@MarkKnol насправді це перевірка виконання, але приводить також до машинописної здатності розуміти певний тип (тобто: ви можете мені довіряти, що це буде тип X або Y, тому що я перевіряю його під час виконання).
Флавіен Волкен

3
Ви можете подумати про використання, (pet as Fish)оскільки tslinter поскаржиться на (<Fish>pet). Дивіться tslint doc
Брайан

1

Для цього можна скористатися instanceofоператором. Від MDN:

Оператор instanceof перевіряє, чи з'являється властивість прототипу конструктора з'являється де-небудь у ланцюзі прототипу об'єкта.

Якщо ви не знаєте, що таке прототипи та прототипи, я настійно рекомендую шукати. Також наводимо приклад JS (TS працює в цьому відношенні), який може уточнити концепцію:

    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
    
    

Прототип ланцюга в цьому прикладі:

тварина> Animal.prototype> Object.prototype

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.