2015-07-27 3 views
1

Я удивлен, что я не могу использовать между интерфейсами.Как отличить между интерфейсами

interface IA { 
    a:string; 
} 

interface IB { 
    b:string; 
} 

class example implements IA, IB { 
    public a:string; 
    public b:string; 
} 

var a : IA = new example(); 

// nope - "Neither IA nor IB are assignable to each other" 
var b : IB = <IB>(a); 

Каков ожидаемый способ сделать это. Кастинг через любой?

// ok 
var c : IB = <IB><any>(a); 

ответ

2

Если у вас есть example, он будет счастлив принять утверждение типа в любом IA или IB, поскольку он совместим с обоими этими типами.

IA не совместим с IB, поэтому компилятор предупредит вас, если вы попытаетесь использовать утверждение типа.

Вы можете выполнить безопасное расширение типа, используя следующие:

var c : IB = <example> a; 

Или, если вам нужно жонглировать совершенно несовместимых типов, вам придется расширить до any первых:

var c: IB = <IB><any>(crazy); 

Я предпочитаю код на самом деле должен был бы изменить эту строку - в этом случае вам не нужно много манипулировать вещами (т. е. сообщить компилятору, что у вас есть экземпляр example:

var a = new example(); 

Целью литья является указание компилятору, что вы хотите использовать экземпляр как тип, который он не может вывести. Предотвращение кастования между интерфейсами просто кажется непоследовательным, непригодным и не предотвращает никаких ошибок. Я не понимаю, почему он не следует за C# и ведет себя как классы вниз.

Приведенный выше пример проверен, так что он безопасен по типу.

// Allowed 
var c : IB = <example> a; 

// Not Allowed 
var c : IB = <example> "test"; 

Таким образом, хотя вы предлагаете уширенный тип для переменной a, это эквивалентно C#, в том, что компилятор знает, что a совместит с example, а также IA. Разница в том, что информация этого типа является структурной, а не номинальной. a также может быть совместим со многими другими типами вашего приложения - особенно, если вы являетесь сторонником принципа разделения сегрегации.

Запрет прямого использования IA в переменной с типом IB предотвращает присвоение несовместимых типов. Сначала проверяются типы, но структура также доступна.

Вполне возможно, что другой программист может назначить {a: 'x'} переменной a. На этом этапе вы будете рады, что TypeScript предупреждает вас о том, что тип не может быть расширен до example с использованием вышеуказанного кода, поскольку он прав, и он просто предотвратил ошибку времени выполнения.

Вы можете достичь именно то, что вы хотите либо:

  1. Декларирование a как типа example - это то, как вы собираетесь использовать переменную так что довольно честно.
  2. Объявление a как тип IA, с использованием типа безопасного расширения до example, если вы хотите использовать его от example. Расширение проверяется компилятором.
  3. Заявить a как тип any. Если вы считаете, что знаете лучше, чем компилятор, вы можете иметь полный контроль и ответственность.

Таким образом, вы можете выбрать, какой уровень контроля вы хотите взять у компилятора. Моя рекомендация - первый вариант выше - используйте тип, который отражает то, как вы действительно будете использовать значение. Это самое близкое к тому, к чему вы будете использовать в C#, как если бы у вас был метод, принимающий IEnumerable, вы не стали бы пытаться использовать его в List внутри метода. Если вам нужен список, вы должны убедиться, что подпись метода попросила его (при этом признавая принцип запроса общих типов и возврата определенных).

+0

Целью кастинга является указание компилятору, что вы хотите использовать экземпляр как тип, который он не может вывести. Предотвращение кастования между интерфейсами просто кажется непоследовательным, непригодным и не предотвращает никаких ошибок. Я не понимаю, почему он не следует за C# и ведет себя как классы вниз. – daw

+0

@daw Я добавил больше информации в свой ответ, вместо того, чтобы пытаться сжать все это здесь. – Fenton

+1

Удивительный, приятное дополнение, спасибо. Структурная типизация - ключевое понимание разницы. Как вы можете ожидать, пример не похож на реальное использование в мире, которое больше похоже на, например. Слияние (a: IThing, b: IThing), где IThing должен быть подавлен к чему-то конкретному, который будет реализован. – daw