TypeScript особенности разработки
Эволюция JS
JS compilers Список всевозможных трансляторов и диалектов: goo.gl/EAabNP (340+) — CoffeeScript family: 12 — CoffeeScript friends (philosophically related): 25 — Static typing: 16 (TypeScript, Dart, Typecast.js, AtScript, ...) — X-language compilers: Java, Ruby, Python, PHP, Erlang, Perl, Lua, Scala, C#, F#, Lisp, Scheme, OCaml, Haskell, Smalltalk, C/C++, Go, ... 3
Достоинства CoffeeScript — Классы — Стрелочные функции, сохранение контекста (=>, ->) — Безопасные сравнения === меньше ошибок — Краткость — ... и много чего другого 5
Почему не CoffeeScript? — Это другой язык — Краткость не всегда сестра таланта. Иногда брат Морзе — Приходится уметь работать с 2мя языками — Если вдруг прекратится поддержка, что делать? — Есть проблемы с поиском разработчиков 6
TypeScript Светлое будущее ES6+ уже вчера
Достоинства TypeScript — TS - это и есть ES6+ — Режимы транспилирования: ES3, ES5, ES6 — Поддержка модулей: Commonjs, AMD — Class, public, private, protected, static... — Статическая типизация — Дополнительно: Interface, Enum, tuple, ... 8
Мифы о TypeScript
Мифы о TypeScript 1. Это другой язык, как и CoffeeScript 2. Закрытый исходный код 3. Разрабатывать можно только в VisualStudio 4. Корректно работает только с Windows 5. Генерит лишний код 6. Медленный 10
Это другой язык, как и CoffeeScript let say = (def:string):string => `TypeScript is ${def}!`; say('pretty amazing') 11
Закрытый исходный код Исходники по адресу: https://github.com/Microsoft/TypeScript/ 12
Разрабатывать можно только в Visual Studio IDE supports — ★ WebStorm, PhpStorm, ... — ☆ Sublime Text (2,3) — Atom (atom.io) — TypeEcs for Eclips (typecsdev.com) — MS Visual Studi☺ 13
Корректно работает только с Windows npm install -g typescript tsc my_application.ts 01. 02. 14
Генерит лишний код var say = (def:string):string => `TypeScript is ${def}!`; say('pretty amazing'); 15
Генерит лишний код var say = (def:string):string => `TypeScript is ${def}!`; say('pretty amazing'); Результат: var say = function (def) { return ("TypeScript is " + def + "!"); }; say('pretty amazing'); 16
Тот же результат на CoffeeScript (function() { var say; say = (function(_this) { return function(def) { return "TypeScript is " + def + "!"; }; })(this); say('pretty amazing'); }).call(this); 17
var gvstr; var _this = this; // Babel делает так же var say = function (def) { return _this.gvstr = "T..." + def + "!" }; say('pretty amazing'); (function() { var say; say = (function(_this) { return function(def) { return "T..." + def + "!"; }; })(this); say('pretty amazing'); }).call(this); TypeScript vs CoffeeScript. Результат компиляции 18
Генерит лишний код enum Color { Red, Green, Blue } var color :Color = Color.Green; 19
Генерит лишний код var Color; (function (Color) { Color[Color["Red"] = 0] = "Red"; Color[Color["Green"]= 1] = "Green"; Color[Color["Blue"] = 2] = "Blue"; })(Color || (Color = {})); var color = 1; 20
Генерит лишний код const enum Color { Red, Green, Blue } var color :Color = Color.Green; Результат: var c = 1; 21
Реальная практика использования TypeScript
Способы подключения — FileWatchers in IDE — TypeScript Compiler in IDE — tsc, grunt, gulp, ... 23
TypeScript Compiler File → Settings → Language & Frameworks → TypeScript → Enable TypeScript Compiler 24
Управляющие комментарии
/// <reference path="file-name.d.ts" /> 26
/// <amd-module name="myName" /> /// <amd-module name="lib/md5" /> function md5() { ... } export = md5; define("lib/md5", ["require", "exports"], function (require, exports) { function md5() { ... } return md5; }); 27
/// <amd-dependency path="dir/file" /> /// <amd-dependency path="lib/global" /> define(["require", "exports", "lib/global"], function (require, exports) { ... }); 28
///<amd-dependency path="file" name="var"/> /// <amd-dependency path="legacy/base/view" name="View" /> View.someDo(); define(["require", "exports", "legacy/base/view"], function (require, exports, View) { View.someDo(); } ); 29
<amd-dependency path="..." name="..." /> /// <reference path="legacy/base/view.d.ts" /> /// <amd-dependency path="legacy/base/view" name="View" /> Эквивалентно записи: /// <reference path="legacy/base/view.d.ts" /> import View = require("legacy/base/view"); 30
/// <reference no-default-lib="true" /> 0_o 31
Подключение существующего legacy кода
Пример подключения *.js в *.ts — newApp.ts — lib/crypt.js 33
lib/crypt.js define(function () { function md5() { /* ... */ } function uid() { /* ... */ } return { md5: md5, uid: uid } }); 34
newApp.ts class AppController { private _uid: string; constructor() { ... } setUid(): string { return this._uid = crypt.uid(); // crypt в legacy } init(): void { ... } run(): void { ... } static exec(ctrl: AppController): void { ... } } export = AppController; 35
newApp.ts /// <amd-dependency path="lib/crypt" /> class AppController { setUid(): string {} } define(["require", "exports", "lib/crypt"], function (require, exports) { var AppController = (function () { function AppController() {} AppController.prototype.setUid = function () { this._uid = crypt.uid() }; return AppController; })(); return AppController; }); 36
newApp.ts /// <amd-dependency path="lib/crypt" /> declare var require:any; var crypt = require("lib/crypt"); class AppController { ... } define(["require", "exports", "lib/crypt"], function (require, exports) { var crypt = require("lib/crypt"); var AppController = (function () { function AppController() {} AppController.prototype.setUid = function () { this._uid = crypt.uid() }; return AppController; })(); return AppController; }); 37
crypt.d.ts declare module "lib/crypt" { export function md5() :string; export function uid() :string; } 38
newApp.ts /// <require path="lib/crypt.d.ts" /> import crypt = require("lib/crypt"); class AppController { ... } define(["require", "exports", "lib/crypt"], function (require, exports, crypt) { var AppController = (function () { function AppController() {} AppController.prototype.setUid = function () { this._uid = crypt.uid() }; return AppController; })(); return AppController; }); 39
TypeScript + React
TypeScript ничего не знает про JSX render: function() { return <div className="train"> <div className="title">{this.state.title}</div> </div> } 41
TypeScript умеет жить с React render: function() { return React.jsx( "<div className="train"> <div className="title">{this.state.title}</div> </div>" ) } 42
React Templates — npm install react-templates -g — npm install grunt-react-templates --save-dev — WebStorm plugin: http://plugins.jetbrains.com/plugin/7648 Документация: wix.github.io/react-templates 44
Пример работы TS c RT(JSX) Структура компонента .../page/train/seats/carMap/carMap/ — carMapItem — carMapItem.rt — carMapItem.rt.js — carMapItem.js / carMapItem.ts — modelFactory.ts 45
carMapItem.rt <rt-require dependency="bemp/blocks/popup/component" as="Popup"/> <rt-require dependency="bemp/blocks/train/seats/carMap/legend/component" as="Legend"/> <div class="car_wrapper"> <Ereg isAvailable={this.props...} schemeHeight={this...} className="..."> </Ereg>{this.props.children}<div class="..." rt-if="..."> <Popup innerHtml={this.props.errorMessage} active="{!this.state.popupHiddenByClick}" onClose={this.onPopupClosed}></Popup> </div> <Legend rt-if="this.props.showLegend" className="..."/> </div> 46
carMapItem.rt.js define([ 'react/addons', 'lodash', 'bemp/blocks/popup/component', ... ], function (React, _, Popup, ...) { 'use strict'; return function () { return React.createElement('div', {...}, React.createElement(Ereg, { 'isAvailable': this.props.isEregAvailable, ... }), this.props.errorMessage ? React.createElement('div', {...}, React.createElement(Popup, { 'innerHtml': this.props.errorMessage, 'onClose': this.onPopupClosed })) : null, ... }; }); 47
carMapItem.js define(['react', './carMapItem.rt', ...], function (React, template, ...) { return React.createClass({ displayName: 'carMapItem', getDefaultProps: function () { return { ... } }, checkErrorMessage: function (props) { ... }, getInitialState: function () { return { ... } }, onPopupClosed: function () { this.setState({ ... }) }, render: template }); }); 48
carMapItem.ts import React = require("react"); import template = require("./carMapItem.rt"); class carMapItem extends React.Component { public displayName:string = 'carMapItem', static defaultProps = { ... onErrorShow: () => void 0 } getInitialState() { return { ... } } onPopupClosed() { this.setState({ ... }) } render() { return template } } export = carMapItem; 49
TypeScript или Facebook Flow?
TypeScript или Babeljs?
TypeScript vs Babel — TypeScript — это Babel + Flow — Babel — это TypeScript без проверки типов 52
Выбираем Flow если ... — ... хочется JSX — ... хочется Babel JS, но не хочется MS TS 53
Что нравится в Flow — Режимы типизации — Проверка типов без указания — Возможность явно указать типы как в TypeScript — Нативная поддержка JSX 54
Что не нравится в Flow — Официально поддерживаются платформы: Mac, Linux, Windows — Распространяется в виде бинарника — Нет (не было) хорошей поддержки в IDE 55
Почему нам нравится TypeScript
Почему нам нравится TypeScript — Пишем на ES6+ — Типизация защищает от опечаток и ошибок — Возможность описывать интерфейсы — Инструменты для реализации ООП — Бекендеры понимают наш код! — Возможность управлять AMD — Активное развитие и поддержка от MS. Уже доступен TS 1.5 beta 57
TypeScript обрастает инструментами — Definition manager http://definitelytyped.org/tsd/ — Doc generator http://typedoc.io/ — Различные плагины для IDE, grunt, gulp, ... 58
TypeScript завтра — ES6 module support, decorators, computed properties, for..of — AMD-dependency optional names — Настройка поведением через конфиг tsconfig.json — Angular 2.0 59
Вопросы?
TypeScript Особенности разработки Александр Майоров, Tutu.ru — mayorov@tutu.ru — majorov.su Презентация: frontendconf.majorov.su 61

TypeScript: особенности разработки / Александр Майоров (Tutu.ru)