Если у вас есть 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
с использованием вышеуказанного кода, поскольку он прав, и он просто предотвратил ошибку времени выполнения.
Вы можете достичь именно то, что вы хотите либо:
- Декларирование
a
как типа example
- это то, как вы собираетесь использовать переменную так что довольно честно.
- Объявление
a
как тип IA
, с использованием типа безопасного расширения до example
, если вы хотите использовать его от example
. Расширение проверяется компилятором.
- Заявить
a
как тип any
. Если вы считаете, что знаете лучше, чем компилятор, вы можете иметь полный контроль и ответственность.
Таким образом, вы можете выбрать, какой уровень контроля вы хотите взять у компилятора. Моя рекомендация - первый вариант выше - используйте тип, который отражает то, как вы действительно будете использовать значение. Это самое близкое к тому, к чему вы будете использовать в C#, как если бы у вас был метод, принимающий IEnumerable
, вы не стали бы пытаться использовать его в List
внутри метода. Если вам нужен список, вы должны убедиться, что подпись метода попросила его (при этом признавая принцип запроса общих типов и возврата определенных).
Целью кастинга является указание компилятору, что вы хотите использовать экземпляр как тип, который он не может вывести. Предотвращение кастования между интерфейсами просто кажется непоследовательным, непригодным и не предотвращает никаких ошибок. Я не понимаю, почему он не следует за C# и ведет себя как классы вниз. – daw
@daw Я добавил больше информации в свой ответ, вместо того, чтобы пытаться сжать все это здесь. – Fenton
Удивительный, приятное дополнение, спасибо. Структурная типизация - ключевое понимание разницы. Как вы можете ожидать, пример не похож на реальное использование в мире, которое больше похоже на, например. Слияние (a: IThing, b: IThing), где IThing должен быть подавлен к чему-то конкретному, который будет реализован. – daw