Как стать автором
Обновить

Комментарии 33

Спасибо конечно за статью, но получилось сумбурно и непоследовательно.
Я как раз перехожу на тайпскрипт и действительно хотел узнать, каковы минусы (о плюсах, как вы и сами заметили, уже сказано довольно много). Полный развернутый анализ плюсов и минусов был бы очень полезен.
Однако вместо этого вы просто вставили довольно очевидную вставку про статическую типизацию, явно для увеличения размера статьи. И ещё цитаты там всякие, что тоже не очень нужно.
В общем, я может и редиска и многого хочу, но вот чего бы я действительно хотел узнать

Не все браузеры поддерживают отладку TypeScript в консоли без лишних настроек.
Действительно ли это доставляет проблем? Говорят, что сгенеренный JS обычно настолько прост, что вообще не составляет проблем его дебажить без всяких сорсмапов. Правда или врут? Если правда, то минус сугубо теоретический.
Множество нетривиальных классов. Чтобы писать код, опираясь на классы, приходится держать в голове какое свойство где находится. Например вместо одного класса Event существуют еще такие как MouseEvent, TouchEvent, KeyboardEvent и другие…
Это ж браузерные классы, а не тайпскриптовые. Или я чего-то не понял в этом минусе, или вы что-то не то говорите.
Неявная статическая типизация. Всегда можно описать тип как any, что по факту отключит приведение к конкретному типу этой переменной.
Опять же. Насколько это реальная практическая проблема? Действительно ли всякие ленивые люди это делают, и это доставляет какую-то боль?
d.ts декларации поддерживаются сообществом DefinitelyTyped и часто не соответствуют текущей версии библиотеки. Либо не учитывают сложных вариантов (generic-функции, возвращаемые значения нескольких типов)
И опять же хотелось бы примеров — насколько часто такое встречается, и насколько много проблем доставляет.
Вот как-то так. В общем, если бы вы правда расписали проблемы языка с точки зрения практического использования, было бы круто. Ну и плюсы тоже конечно были бы в тему для сравнения, но это второстепенно — про них и правда говорят везде.
Говорят, что сгенеренный JS обычно настолько прост, что вообще не составляет проблем его дебажить без всяких сорсмапов.
Правда. У меня ни разу не было желания как-то настраивать браузер, чтобы можно было дебажить именно .ts код. .js генерятся очень понятные. Вот если бы можно было дебажить TS прямо в студии — это было бы действительно классно, но я такой возможности не нашёл.

Насколько это реальная практическая проблема?
На мой взгляд это не проблема при минимальном уровне дисциплины в команде. Хотя, конечно, если использовать any везде, то будет боль. Но записывать это в минусы языка я бы не стал. dynamic же в минус шарпу не ставят.

d.ts декларации поддерживаются сообществом DefinitelyTyped и часто не соответствуют текущей версии библиотеки.
Если критично использовать последние версии или редкие библиотеки — то возможно будут проблемы с d.ts. Но никто не мешает работать с JS файлами через any или написать свой файл определений.

Либо не учитывают сложных вариантов (generic-функции, возвращаемые значения нескольких типов)
У меня за полтора годы работы такое было один раз. Пришлось повозиться, но большой проблемы я не вижу.
Вот если бы можно было дебажить TS прямо в студии — это было бы действительно классно, но я такой возможности не нашёл.

Если вы запускаете проект в IE, то такая возможность по умолчанию есть.
Спасибо, не знал.
Спасибо за столь развернутый комментарий. Постараюсь ответить на Ваши вопросы:
Не все браузеры поддерживают отладку TypeScript в консоли без лишних настроек.

Действительно ли это доставляет проблем? Говорят, что сгенеренный JS обычно настолько прост, что вообще не составляет проблем его дебажить без всяких сорсмапов. Правда или врут? Если правда, то минус сугубо теоретический.

Согласен с вами, что в большинстве случаев хватает дебажить итоговый JS, но в крупных проектах, если у вас есть множество классов, контроллеров, вью моделей, то гораздо приятнее дебажить именно их. Сам сталкивался с такой проблемой, что без проблем получается отлаживать конечный код на ts только в браузере IE. Во всех остальных приходится делать манипуляции с .map файлами, дабавляя их в соответвующую директорию на сервере.

Множество нетривиальных классов. Чтобы писать код, опираясь на классы, приходится держать в голове какое свойство где находится. Например вместо одного класса Event существуют еще такие как MouseEvent, TouchEvent, KeyboardEvent и другие…

Это ж браузерные классы, а не тайпскриптовые. Или я чего-то не понял в этом минусе, или вы что-то не то говорите.

Лично сталкивался со случаем вида (event).keyCode, где keyCode нет в классе Event.

Неявная статическая типизация. Всегда можно описать тип как any, что по факту отключит приведение к конкретному типу этой переменной.

Опять же. Насколько это реальная практическая проблема? Действительно ли всякие ленивые люди это делают, и это доставляет какую-то боль?

Считаю это плохой практикой, т.к используя any вы лишаете себя основной возможности TypeScript — проверки типов. К примеру описав параметр функции как any, вы должны валидировать ее тип самостоятельно.

d.ts декларации поддерживаются сообществом DefinitelyTyped и часто не соответствуют текущей версии библиотеки. Либо не учитывают сложных вариантов (generic-функции, возвращаемые значения нескольких типов)

И опять же хотелось бы примеров — насколько часто такое встречается, и насколько много проблем доставляет.

Пример — knockoutjs сейчас имеет версию 3.4.0, а в DefinitelyTyped есть определения пока еще только для версии 3.2.0
Спасибо, не знал, что IE поддерживает ts напрямую. Крутая фича, даже интересно стало попробовать.

Лично сталкивался со случаем вида (event).keyCode, где keyCode нет в классе Event.
Я ж говорю, это исключительно браузерные классы. Откройте любую консоль и поиграйтесь как я.

Тайпскрипт тут не может ничего ни добавить, ни изменить.
Этих классов, кстати, вообще не будет, если вы будете писать на TS под NodeJS
Что вы подразумеваете под браузерными классами? В моем случае если написать следующий код, при компиляции TS вернет ошибку:
image
Я подразумеваю, что Event — это часть Web API developer.mozilla.org/ru/docs/Web/API/Event
И да, там нету keyCode, смотрите выше скрин из консоли. Потому что у Event много наследников. И например у WheelEvent нет keyCode. И ещё у многих других его тоже нету.
Ошибка у вас потому что (event) может быть объектом как KeyboardEvent (где есть keyCode), так и например WheelEvent, где keyCode нету.
В общем, нужно честно описывать, какого именно ивента вы ждёте.
Лично я, работая с TypeScript с версии 1.3, многократно сталкивался с проблемой неверной/неполной декларации библиотек, но это как я считаю проблема в том, что декларацию чаще всего пишут не сами создатели js-библиотеки, а кто-то постороний и делает это в спешке, т.к. зачастую небывает описаний к функциям или параметрам.
Неявная статическая типизация. Всегда можно описать тип как any, что по факту отключит приведение к конкретному типу этой переменной.


В найстроках конфига для проекта можно запретить все типы any. Тогда компилятор заставит все описывать. Так что это опционально.
За это время мы привыкли друг к другу и пережили много успехов и разочарований.

А собственно где успехи, где разочарования?

Если пройтись по минусам, то тут тоже не всё так однозначно:
  1. В процессе разработки имеем дело с файлами *.ts, *.d.ts, *.map, *.js. Слишком много дополнительных файлов, что бывает неудобно, если ваш проект небольшой.
    Два последних известным всем тем, кто хоть немного сталкивался с front-end'ом. Первый, это собственно сам код (к слову, *.js -> *.ts ничего не сломает, но, думаю, вы об этом и так знаете)
  2. Не все браузеры поддерживают отладку TypeScript в консоли без лишних настроек.
    Если высказали проблему, то может как-то расширить её — с чем столкнулись, как решали? Я, например, к сожалению, не сталкивался и было бы очень интересно прочитать про опыт других.
  3. Множество нетривиальных классов. Чтобы писать код, опираясь на классы, приходится держать в голове какое свойство где находится. Например вместо одного класса Event существуют еще такие как MouseEvent, TouchEvent, KeyboardEvent и другие...
    Частично соглашусь, но с оговоркой, что вы только начали работать с языком. Впоследствии это как-то не замечается, возможно только у меня.
  4. Неявная статическая типизация. Всегда можно описать тип как any, что по факту отключит приведение к конкретному типу этой переменной.
    Не соглашусь. Это скорее feature самого языка. Кроме того, проблему всегда можно решить. Можно, например, начать с этого.
  5. Это транспайлер, что подразумевает, что мы должны всегда иметь под рукой tsc
    Если вспомнить, что мы работаем с языком, который нужно ещё компилировать — проблема как-то угасает. Дотнетчики не жалуются, что им нужен csc.exe :) Ну и не стоит забывать про то, что сейчас всё чаще и чаще всё собирается, компилируется с использованием grunt, gulp или webpack
  6. d.ts декларации поддерживаются сообществом DefinitelyTyped и часто не соответствуют текущей версии библиотеки. Либо не учитывают сложных вариантов (generic-функции, возвращаемые значения нескольких типов)
    В этом и есть весь challenge — вы можете стать частью огромного сообщества, которое изменяет мир open source. Исправили/добавили что-то — в следующий раз кто-то поможет и вам.


Впрочем, комментарий и так слишком длинный.
Спасибо за статью — кто-то обязательно подчерпнёт для себя что-то новое и интересное.
Ощущение от TypeScript сменяется от энтузиазма относительно compile-time валидации кода до ощущения постоянной незавершенности. Ожидаешь некоторой жесткости в обмен на широкие возможности рефакторинга, но в текущих версиях инструментов их нет.

Отдельные эмоции от переписывания старого кода — в условиях нехватки времени подкупает возможность переименовать файлы и пользоваться обратной совместимостью. В команде это ведет к неподконтрольному росту использования any и как следствие улучшения качества конечного кода не наблюдается. Можно использовать флаг в tsconfig, запрещающий использование any, но гибкость тогда отпадает. Возможно в маленьком проекте и можно было бы переехать полностью, но заставлять описывать все интерфейсы — чрезчур жестоко для людей которые в разработке изначально с frontend.

Возможно это предвзятое мнение, сформированное ожиданием некоего браузерного C#, коим TypeScript конечно не является.
Хотите писать без головной боли — пишите на Haxe. TS в сравнении с Haxe — надувная баба. Причем проколотая, которую надо все время подкачивать. Почему баба? Потому, что идешь за удовольствием, а получаешь немного не то. Но пыжишься… пыжишься :D
это одно из достоинств языка и проверка типов переоценена.


Типы в контексте старого JS не нужны, да. Но в процессе разработки это ой как важно. Весьма приятно писать так:

var myArray : Array<MyClass>;


и при написании кода

myArray[i]. после точки начинать получать выпадающий списк с публичными методами из MyClass :)

Вот так работает Haxe, например.
Минусуйте на здоровье :) С меня тоже ржали колхозники, когда я огород за 15 минут бабушке вспахал мотоблоком :) Причем ржали громче всех те, у кого максимально большие мозоли на руках от лопаты были :D
Согласен, что с TS intelisense работает лучше. Но и в чистом JS не всё так плохо.
image

image

Хотя да, из-за возможной разнородности массива intelisense не срабатывает.
TypeScript — даёт во-многом иллюзию строгой типизации. Когда вам с сервера приезжает некий объект и вы начинаете верить в то, что это именно IProductsResponse, но проблема в том, что схема объекта может измениться и Typescript вам об этом не скажет.
TypeScript — это как документация, поможет, если её поддерживать, но она и требует кучу накладных расходов на ведение. Нужно писать кучу интерфейсов, только чтобы не писать any. Ибо, ололо, any — это не TypeScript way.
Typescript учит отказываться от изменяемых схем объектов в пользу наследования и это уменьшает гибкость JS. А в JS совершенно нормально получить request и напихать туда полей и получить ViewModel, а в TS надо интерфейсы на всё. В итоге, кода получается больше.

А *.d.ts — это вообще ад: нет для новых версий, нет для непопулярных библиотек. Обновление библиотек превращается в кошмар, ибо надо обновлять *.d.ts для всего этого.

Лично для меня, и в очень большом проекте, TypeScript — это много накладных расходов ради какого-то маленького приемущества над JS в виде Intelisense и чуть лучший анализ кода.
Юзайте es6 — это хорошо.
Поддерживаю, у TypeScript нет TypeScript-way. Набор каркасиков, которые как-то поддерживают код. Хочешь укрепляй, а хочешь брось так. Как правильно транспилить в проекте с gulp? Допустим с помощью gulp-typescript. Для этого надо отключить компиляцию в VisualStudio и WebStorm. Добавить JS файлы в gitignore? Для смешанного подхода — не то. Вообще хоть кто-то коммитит сгенерированные JS? Конкретного ответа нет.
>схема объекта может измениться и Typescript вам об этом не скажет.
А JS скажет? В случае изменения объекта, код что в JS, что в TS нужно будет менять, только в TS это будет сделать проще.

>маленького приемущества над JS в виде Intelisense и чуть лучший анализ кода.
А мне вот не кажется, что это маленькое преимущество. В JS нужно постоянно помнить, какие поля у меня содержит данный объект и постоянно лезть смотреть в код объявления, как именно там названы поля или функции. Непрекращающаяся боль для меня это.
А JS скажет?

JS не делает вид, что он «строго типизированный». C ТS вы чувствуете себя как бы немного обманутым: интерфейс вы определили, но он ничего не ограничевает, только даёт Resharper'у переименовать поле в случае чего.
Да, это функция полезная если вы саппортите проект, но крайне уныло применять TS, когда у вас быстро развивающийся проект, в котором спека меняется часто.
Потом помните, что хуже отсутствия документации может быть только документация, которая вам нагло врёт. Вот TS вам легко позволит сделать такую. Вам с сервера будет приходить id:string, а в интерфейсе у вас будет id:number или наоборот. Вы очень не скоро поймёте в чём дело, ибо вы будете верить интерфейсам. Чистый JS в этом плане «честнее», он вам сразу ничего не обещает, наоборот, с чистым JS у вас есть безнаказаная возможость менять тип поля и схему объекта в рантайме. Да, может, это не «архитектурно», но, порой, в разы уменьшаяет количество кода и скорость разработки.

А мне вот не кажется, что это маленькое преимущество.

Да, TS говорит о том, что это огромное приемуществно и в теории оно как бы так. Но на лично моей практике, что проще посмотреть в код, чем саппортить кучу интерфейсов.
У меня самая частая операция, это добавление поля в response API. В случае fullstack-js вы добавляете поле в объект mongo + валидатор mongo, и поле уже доступно вам во viewModel ангуляра. А если у вас TypeScript, то по идее вам надо «прокинуть» его через кучу интерфейсов, либо везде писать any.

Хочешь укрепляй, а хочешь брось так.

Если не делать объектам интерфейсы, а писать any, то тогда зачем нужен TS?
Вот у нас корпоративный стайлгайд разработан с требованием минимизировать количество any в коде. Это как бы хорошо, но замедляет разработку.

Хочешь скопипастить пример кода, а он, в 99% случая, на JS. И вот сидишь и делаешь обратную трансляцию из js в ts, определяешь интерфейсы. Тебя постоянно наказывают за модификацию кода необходимостью декларации интерфейсов.
TS превносит рутину в разработку и делает её дороже.
Заголовок спойлера
С одной стороны John Papa со своими гайдами, с другой TS с интерфейсами, куды бедному говнокодеру-копипастеру податься…


Добавить JS файлы в gitignore?

Мы заливаем генерённые JS, да бывают конфликты, но мы просто перетираем js при мердже.
Тактика такая, что лучше иметь проверенный JS в репе, чем получать сайд-эффекты от кривой версии пакетов или самих bower, gulp, typescript. Трансляция/бандлинг/минификация тоже может приносить ошибки, к тому же это лучше для разделения труда. Тестер, которому нужно развернуть у себя проект не должен делать все эти npm install, bower install и т.п.
Мы пользуемся прекрасным Web Essentials 2013 он всё транслирует на лету и красиво показывает TS|JS код. Если у всех одна и та же версия WE и typescript, то проблем не возникает. В VS 2015 всё сложнее, там сломали Web Essentials, теперь там проще использовать gulp.
При попытке подружить TS с каким-нибудь экзотическим фреймворком возможны проблемы. Особенно если этот фреймворк самостоятельно генерирует код и html. Попробуйте например использовать Vue.js совместно с TypeScript, энтузиазма сразу поубавится.
Ещё один недостаток TS — сложности с автогенерированием документации.
jsdoc по вполне понятным причинам не работает, а если использовать разного рода костыли для его подключения, в аннотациях приходится дублировать информацию о типах (при том, что тот же WebStorm вполне способен производить проверку типов по аннотациям в чистом JS, и получается почти как язык с типизацией).
Т.е. нужен нормальный инструмент для генерации документации. Инструмент, способный вытаскивать информацию о типах непосредственно из кода, чтоб в аннотации только собственно описание вносить надо было. Пока что с этим проблемы.
А в чем, собственно, проблема? Для Vue.js открыто issue на github и люди активно что-то предлагают, например такой вариант vue-typescript
Насчёт доков и jsdoc тоже какая-то натянутая проблема — открываем typedoc, читаем и радуемся.
jsdoc по вполне понятным причинам не работает

кстати уже есть пулл реквест который добавляет поддержку JSDoc
Недавно изучал TypeScript. Выводы в основном положительные. Но есть ряд вещей которые я так и не понял:

1. Как импортировать другой файл TypeScript, что бы он вкомпиливался в результирующий файл? Т.е. как в обычных языках — пишешь импорт такой то класс и все. А вот с TypeScript такое не пройдет — надо указывать в html дополнительно этот файл. Или есть способ проще и элегантнее без большой писанины?

2. Приватные переменные только проверяются на стадии компиляции — но на самом деле они публичные и если предок и наследник имеют приватную переменную с одним и тем же именем — будет просто ошибка компиляции. Это как то не продумано.

Пробовал в Visual Studio 2015
Как импортировать другой файл TypeScript,


Еще плюс Haxe:

import com.packagename.MySecondClass;
...
var m2c : MySecondClass = new MySecondClass();


и он сам всё вкомпилирует в результирующий JS

2. Приватные переменные только проверя..

Снова сравниваю с Haxe

public var myPublic : Int = 0;
private var myPrivate : Int = 0;
public static var myStaticPublic : Int = 0;
private static var myStaticPrivate : Int = 0;


P.S. я понимаю, что речь тут о TypeScript. Но для сравнения с другими языками это полезно знать :) Особенно тем, кто только решает на чем его JS писать :)
Да безусловно Haxe в данных вопросах лучше. Он делался по образу и подобию AS3. Но он тоже не лишен недостатков — а их у него очень много. И да я пишу на Haxe сейчас. Просто тут обсуждение TypeScript и хотелось бы узнать побольше о нем )
1. Как импортировать другой файл TypeScript, что бы он вкомпиливался в результирующий файл?

tsc --out D:\ts\output.js D:\ts\app.ts D:\ts\hello.ts

в данном случае 2 файла app.ts и hello.ts скомпилируются в 1 output.js

2. Приватные переменные только проверяются на стадии компиляции — но на самом деле они публичные и если предок и наследник имеют приватную переменную с одним и тем же именем — будет просто ошибка компиляции. Это как то не продумано.

Тут я с вами согласен. Это вызвано тем, что в JavaScript невозможно задать приватные поля. Они просто не предусмотрены спецификацией языка.
Ну лично я не поклонник командной строки, прописывать каждый файл который надо скомпилить — это тот еще ад. Проще указывать по необходимости из файла в фаил.
Если есть возможность компилировать несколько файлов в один, никто не мешает автоматизировать вам этот процесс. Например прописать настройки компиляции при билде в вашем проекте.
Это вызвано тем, что в JavaScript невозможно задать приватные поля. Они просто не предусмотрены спецификацией языка.
Это смотря, что вы понимаете под «приватными полями». Переменные из scope функции-конструктора, доступные через замыкание, вам не подходят?
Оба вопроса связаны с платформой JS и тем, что TypeScript достаточно тонкая надстройка.

1) импорты появились в ES6, поэтому достаточно TS 1.7 скомпилировать в ES6, а ES6 в ES5. Насколько такая схема сейчас работает с разными видами IDE, систем сборки и версиями TypeScript не скажу.
2) в JS нет приватных переменных, не стали придумывать усложнение, достаточно ошибки сборки
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории