2014-12-11 4 views
1

У меня была игра с TypeScript и интерфейсами. У меня есть следующий код:Интерфейсы и реализация интерфейса TypeScript

interface Control { 
    name: string; 
    onSelect():string; 
} 

class Button { 
    name:string="button"; 
    onSelect = function() { 
     return "hello"; 
    } 
} 

var a:Button = new Button(); 
var b:Control = {"name": "arbitrary", "onSelect":() => { return "ahoy!"; }}; 

var trigger = function(c:Button) { 
    console.log(c.name, "says", c.onSelect()); 
} 

trigger(a); 
trigger(b); 

Которая компилируется и работает без жалобы. Может ли кто-нибудь объяснить, почему моя функция trigger принимает b, хотя она ожидает получить тип Button и b имеет тип Control.

Даже если Button были явно реализовать Control, я прошу для Button а не Control. Для всех назначенных целей Button может содержать дополнительные элементы.

Является ли TypeScript выводом реализации только потому, что они структурно одинаковы? Разрешено ли передавать интерфейс, где ожидается реализация класса? (Она не должна быть наоборот?)

+1

Если 'Button' имеет частный член, то только его (или классы, которые простираются от него) будут считаться совместимыми. Вы можете подумать о добавлении «фиктивного» частного члена, если это желаемое поведение. –

+0

Я вижу. Я подумывал о добавлении фиктивного члена. На ваш взгляд, строгий тип принуждает что-то ненужное? Это противоречит принципам TS? –

+0

Я бы сказал, что он редко продуктивен, но всегда есть исключения. Это скорее дизайнерский запах, если «триггер» на самом деле зависит от аспектов «Button», отличных от тех, которые он использует, в конце концов. –

ответ

2

Как описано в TypeScript documentation on interfaces:

Одним из основных принципов Машинопись является то, что тип проверка фокусируется на «форме», что ценности имеют. Это иногда называют «утиной типизации»

В "duck typing":

Если это выглядит как утка и плавает как утка, то в ней, скорее всего, утка.

Иными словами, TypeScript рассматривает форму (методы и свойства) поставляемого объекта или типа. Если предоставленный объект содержит все свойства и методы, описанные интерфейсом, то объект может, по всей вероятности, рассматриваться как объект, который совместим с описанным интерфейсом.

В вашем примере ваш интерфейс и класс выглядят точно так же, поэтому TypeScript рассматривает ваш объект как совместимый с описанным интерфейсом.

Если у вас есть examine the generated JavaScript, обратите внимание, что никакого упоминания о вашем интерфейсе вообще нет - это связано с тем, что интерфейсы TypeScript являются, по существу, метаданными типа метаданных, предоставляемыми разработчиками, которые помогают проверять тип соответствия типов.

+0

Есть ли способ для проверки строгого типа? Это облегчает мне возможность упускать из виду тонкие нюансы, которые могут вызвать проблемы на линии. –

+0

@Andrei - Тип безопасности не «JavaScript-способ». Многие программисты JS любят то, что они могут летать быстро и свободно с помощью типов. TS добавляет некоторую безопасность типа, но он все еще слабее, чем C/C++/C#/Java/и т. Д. –

+0

@ Andrie: Кроме того, как отмечает Джон, если вы создадите свой объект или интерфейсы, то TS предупредит вас. –

1

И ваш interface и class имеют ту же реализацию, поэтому в то время как его ожидает Button вы передаете в совместимом объекте (имеют имя, которое возвращает строку и onSelect функции, которая возвращает строку)

Если добавить еще одно свойства до Button, таких как greeting: string будет ошибкой на trigger(b), говоря, что это недействительно.

interface Control { 
    name: string; 
    onSelect:() => string; // this is another way to write function that returns a string 
} 

class Button implements Control { 
    name:string="button"; 
    onSelect = function() { 
     return "hello"; 
    } 
    greeting: string; // adding this will cause trigger(b) to fail 
} 
+0

Знаете ли вы, есть ли способ включить строгую проверку типов? Будет ли это то, что вы считаете ненужным? –

+0

@AndreiNemes Я не думаю, что это необходимо. Как только ваш класс обладает каким-либо другим свойством или не соответствует интерфейсу, он не позволит этого. – John

+0

Спасибо за ваш вклад! –

Смежные вопросы