#typescript
Всем привет. Изучаю тайпскрипт, и в первую очередь меня интересуют интерфейсы. Для проверки того, что как они работают, я написал следующее: interface I1 { stringProp: string; numProp: number; } printI1(i1: I1): void { console.log(i1); console.log(i1.numProp * 2); } От поведения этого интерфейсного типа я ожидаю следующего: В stringProp может попасть только строка, а в в numprop - только число. Интерфейс позволит мне абстрагироваться от полей того типа, который я привожу к нему. Ну хорошо, возьмем такой класс. class T1 { public propNotExistedInInterface: boolean = true; public stringProp: any; public numProp: any; } И попробуем привести его к I1 следующим образом. let a: T1 = new T1(); a.stringProp = 13; a.numProp = "asd"; this.printI1(a); И результат: Object { propNotExistedInInterface: true, stringProp: 13, numProp: "asd" } NaN Ни одного из моих ожиданий не оправдалось. Ни одного предупреждения транслятора. Так в чем заключается хвалёная типизация? пробовал менять NoImplicitAny - один и тот же результат. Следующий пример: Берем интерфейс: interface INumberWithFuncProcessor { num: number; func(number): string; } Мы будем использовать его в качестве параметра метода (при этом допускаем ошибку): useProcessor(param: INumberWithFuncProcessor): string { return param.func(param); // ошибка, подразумевали param.num } И используем наш метод: let something = this.useProcessor( { num: 12, func: (x) => { return x.toString() } }); При попытке вывести something на экран мы увидим [object Object]. Транслятор молчит. По всей видимости в наш параметр интерфейсного типа попадает что-то вроде. { num: number; func(object): string; } Вопрос, как видите, риторический: есть ли статическая типизация в ts, или это просто рекламный ход.
Ответы
Ответ 1
Типизация, очевидно, есть. Просто в данном случае происходят некорректные проверки. Если разобрать первый пример: Есть интерфейс, в котором указаны конкретные поля, и указанным полям проставлен конкретный тип. Что происходит дальше, объявляется класс, у которого присутствуют эти поля, но им задан тип any. Что такое any - это заглушка, которая показывает, что тип может быть любой. В следствие этого переменную типа any можно присвоить переменной любого типа. Что получилось в итоге, компилятор не проверяет реальный тип полей, так как типизация работает только во время компиляции, и чтобы определить какое именно из значений в итоге будет у поля, и, соответственно, какой тип, компилятору нужно выполнить всю программу. В общем случае это неразрешимая задача, и определение типа any отдается на откуп программисту. В то же время, если убрать одно из полей в классе T1, например stringProp, компилятор может проверить, что у объекта передаваемого класса, отсутствуют обязательное поле и кинет ошибку. А также, если вместо any использовать конкретные типы, например public stringProp: number; компилятор опять подскажет, что типы не совпадают. Примеры для проверки Что касается второго примера: interface INumberWithFuncProcessor { num: number; func(number): string; } Ошибочно само описание интерфейса, и при выборе опции noImplicitAny компилятор подсказывает, что number - это параметр, и так как у него не указан напрямую тип, его тип будет any и как мы помним - any не проверяется в compile-time. Таким образом, вполне нормально передавать в него переменные любого типа. Если же указать конкретный тип параметра, например: interface INumberWithFuncProcessor { num: number; func(a:number): string; } То компилятор вполне резонно покажет ошибку: Argument of type 'INumberWithFuncProcessor' is not assignable to parameter of type 'number' Пример для проверки
Комментариев нет:
Отправить комментарий