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


241

В ActionScript можно проверить тип во время выполнения с помощью оператора is :

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

Можно ли определить, является ли переменная (extends или) определенным классом или интерфейсом с TypeScript?

Я не мог найти ничего об этом в спецификации языка. Это должно быть при работе с классами / интерфейсами.

Ответы:


320

4.19.4 Оператор instanceof

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
Брайан

1

Вы можете использовать instanceofоператор для этого. От MDN:

Оператор instanceof проверяет, присутствует ли свойство prototype конструктора где-либо в цепочке прототипов объекта.

Если вы не знаете, что такое прототипы и цепочки прототипов, я настоятельно рекомендую поискать их. Также вот пример 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> Animal.prototype> Object.prototype

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.