Начинаем работу с TypeScript
() translation by (you can also view the original English article)
В конце 2012 года Microsoft представила TypeScript, типизированный суперсет для JavaScript, который компилируется в обычный JavaScript. TypeScript фокусируется на предоставлении полезных инструментов для крупномасштабных приложений путем реализации функций, таких как классы, аннотации типов, наследование, модули и многое другое! В этом уроке мы начнем с TypeScript, используя простые примеры кода с укусом, скомпилируем их в JavaScript и просмотрим мгновенные результаты в браузере.
Установка инструментов
Возможности TypeScript применяются только во время компиляции.
Вы настроите свою машину в соответствии с вашей конкретной платформой и потребностями. Пользователи Windows и Visual Studio могут просто загрузить плагин Visual Studio. Если вы работаете в Windows и не имеете Visual Studio, попробуйте Visual Studio Express для Интернета. Опыт TypeScript в Visual Studio в настоящее время превосходит другие редакторы.
Если вы работаете на другой платформе (или не хотите использовать Visual Studio), все, что вам нужно, это текстовый редактор, браузер и пакет npm для TypeScript для использования TypeScript. Следуйте инструкциям по установке:
- Установка диспетчера пакетов node (npm)
1
$ curl http://npmjs.org/install.sh | sh
2
$ npm --version
3
1.1.70
- Глобально установите TypeScript пакет npm:
1
$ npm install -g typescript
2
$ npm view typescript version
3
npm http GET https://registry.npmjs.org/typescript
4
npm http 304 https://registry.npmjs.org/typescript
5
0.8.1-1
- Любой современный браузер: для этого учебника мы используем Chrome.
- Любой текстовый редактор: для этого учебника используется Sublime Text
- Модуль подсветки синтаксиса для текстовых редакторов



Готово; мы готовы сделать простое приложение «Hello World» в TypeScript!
Hello World в TypeScript
TypeScript является надмножеством Ecmascript 5 (ES5) и включает функции, предлагаемые для ES6. Из-за этого любая программа JavaScript уже является программой TypeScript. Компилятор TypeScript выполняет локальные преобразования файлов в программах TypeScript. Следовательно, окончательный вывод JavaScript точно соответствует вводу TypeScript.
Сначала мы создадим базовый файл index.html
и ссылку на внешний файл сценария:
1 |
<!doctype html>
|
2 |
<html lang="en"> |
3 |
<head>
|
4 |
<meta charset="UTF-8"> |
5 |
<title>Learning TypeScript</title> |
6 |
</head>
|
7 |
<body>
|
8 |
|
9 |
<script src="hello.js"></script> |
10 |
|
11 |
</body>
|
12 |
</html>
|
Это простое приложение «Hello World»; поэтому давайте создадим файл с именем hello.ts
. Расширение *.ts
обозначает файл TypeScript. Добавьте следующий код в hello.ts
:
1 |
alert('hello world in TypeScript!'); |
Затем откройте интерфейс командной строки, перейдите к папке, содержащей hello.ts
, и запустите компилятор TypeScript с помощью следующей команды:
1 |
tsc hello.ts |
Команда tsc
является компилятором TypeScript и сразу генерирует новый файл hello.js
. В нашем приложении TypeScript не используется синтаксис, специфичный для TypeScript, поэтому мы видим тот же самый код JavaScript в hello.js
, который мы написали на hello.ts
.
Круто! Теперь мы можем изучить возможности TypeScript и посмотреть, как это может помочь нам поддерживать и создавать широкомасштабные приложения JavaScript.



Аннотации type
Аннотации типа являются дополнительной функцией, которая позволяет нам проверять и выражать наше намерение в программах, которые мы пишем. Давайте создадим простую функцию area()
в новом файле TypeScript, называемом type.ts
1 |
function area(shape: string, width: number, height: number) { |
2 |
var area = width * height; |
3 |
return "I'm a " + shape + " with an area of " + area + " cm squared."; |
4 |
}
|
5 |
|
6 |
document.body.innerHTML = area("rectangle", 30, 15); |
Затем измените источник скрипта в index.html
на type.js
и запустите компилятор TypeScript с помощью tsc type.ts
. Обновите страницу в браузере, и вы увидите следующее:



Как показано в предыдущем коде, аннотации типа выражаются как часть параметров функции; они указывают, какие типы значений вы можете передать функции. Например, параметр shape
обозначается как строковое значение, а width
и height
- это числовые значения.
Аннотации типов и другие функции TypeScript применяются только во время компиляции. Если вы передадите какие-либо другие типы значений этим параметрам, компилятор даст вам ошибку времени компиляции. Такое поведение чрезвычайно полезно при создании крупномасштабных приложений. Например, давайте намеренно передать строковое значение для параметра width
:
1 |
function area(shape: string, width: number, height: number) { |
2 |
var area = width * height; |
3 |
return "I'm a " + shape + " with an area of " + area + " cm squared."; |
4 |
}
|
5 |
|
6 |
document.body.innerHTML = area("rectangle", "width", 15); // wrong width type |
Мы знаем, что это приводит к нежелательному результату, и компиляция файла предупреждает нас о проблеме со следующей ошибкой:
1 |
$ tsc type.ts
|
2 |
type.ts(6,26): Supplied parameters do not match any signature of call target |
Обратите внимание, что, несмотря на эту ошибку, компилятор сгенерировал файл type.js
. Ошибка не останавливает компилятор TypeScript от генерации соответствующего JavaScript, но компилятор предупреждает нас о потенциальных проблемах. Мы предполагаем, что width
будет числом; передача чего-либо другого приводит к нежелательному поведению в нашем коде. Другие аннотации типа включают bool
или даже any
.
Интерфейсы
Давайте расширим наш пример, включив интерфейс, который далее описывает форму как объект с дополнительным свойством color
. Создайте новый файл с именем interface.ts
и измените источник скрипта в index.html
, чтобы включить interface.js
. Введите следующий код в interface.ts
:
1 |
interface Shape { |
2 |
name: string; |
3 |
width: number; |
4 |
height: number; |
5 |
color?: string; |
6 |
}
|
7 |
|
8 |
function area(shape : Shape) { |
9 |
var area = shape.width * shape.height; |
10 |
return "I'm " + shape.name + " with area " + area + " cm squared"; |
11 |
}
|
12 |
|
13 |
console.log( area( {name: "rectangle", width: 30, height: 15} ) ); |
14 |
console.log( area( {name: "square", width: 30, height: 30, color: "blue"} ) ); |
Интерфейсы - это имена, присвоенные типам объектов. Мы можем не только объявить интерфейс, но и использовать его как аннотацию типа.
Компиляция interface.js
не приводит к ошибкам. Чтобы вызвать ошибку, добавим еще одну строку кода в interface.js
с формой, которая не имеет свойства имени и посмотрим результат в консоли браузера. Добавьте эту строку в interface.js
:
1 |
console.log( area( {width: 30, height: 15} ) ); |
Теперь скомпилируйте код с помощью tsc interface.js
. Вы получите сообщение об ошибке, но не беспокойтесь об этом прямо сейчас. Обновите свой браузер и посмотрите на консоль. Вы увидите что-то похожее на следующий снимок экрана:



Теперь давайте посмотрим на ошибку. Это:
1 |
interface.ts(26,13): Supplied parameters do not match any signature of call target: |
2 |
Could not apply type 'Shape' to argument 1, which is of type '{ width: number; height: number; }' |
Мы видим эту ошибку, поскольку объект, переданный в area()
, не соответствует интерфейсу Shape
; для этого требуется свойство name.
Стрелочные функции
Понимание сферы действия ключевого слова this
является сложной задачей, и TypeScript упрощает его, поддерживая выражения стрелочных функций, новую возможность, обсуждаемую для ECMAScript 6. Стрелочные функции сохраняют значение this
, что значительно упрощает запись и использование функций обратного вызова. Рассмотрим следующий код:
1 |
var shape = { |
2 |
name: "rectangle", |
3 |
popup: function() { |
4 |
|
5 |
console.log('This inside popup(): ' + this.name); |
6 |
|
7 |
setTimeout(function() { |
8 |
console.log('This inside setTimeout(): ' + this.name); |
9 |
console.log("I'm a " + this.name + "!"); |
10 |
}, 3000); |
11 |
|
12 |
}
|
13 |
};
|
14 |
|
15 |
shape.popup(); |
this.name
в строке 7 будет явно пустым, как показано в консоли браузера:



Мы можем легко исправить эту проблему, используя стрелочную функцию TypeScript. Просто замените function()
на ()=>
.
1 |
var shape = { |
2 |
name: "rectangle", |
3 |
popup: function() { |
4 |
|
5 |
console.log('This inside popup(): ' + this.name); |
6 |
|
7 |
setTimeout( () => { |
8 |
console.log('This inside setTimeout(): ' + this.name); |
9 |
console.log("I'm a " + this.name + "!"); |
10 |
}, 3000); |
11 |
|
12 |
}
|
13 |
};
|
14 |
|
15 |
shape.popup(); |
И результаты:



Взгляните на созданный файл JavaScript. Вы увидите, что компилятор ввел новую переменную var _this = this;
, и использовал ее в функции обратного вызова setTimeout()
для ссылки на свойство name
.
Классы с общедоступными и частными модификаторами доступа
TypeScript поддерживает классы, и их реализация тесно соответствует предложению ECMAScript 6. Давайте создадим еще один файл с именем class.ts
, и рассмотрим синтаксис класса:
1 |
class Shape { |
2 |
|
3 |
area: number; |
4 |
color: string; |
5 |
|
6 |
constructor ( name: string, width: number, height: number ) { |
7 |
this.area = width * height; |
8 |
this.color = "pink"; |
9 |
};
|
10 |
|
11 |
shoutout() { |
12 |
return "I'm " + this.color + " " + this.name + " with an area of " + this.area + " cm squared."; |
13 |
}
|
14 |
}
|
15 |
|
16 |
var square = new Shape("square", 30, 30); |
17 |
|
18 |
console.log( square.shoutout() ); |
19 |
console.log( 'Area of Shape: ' + square.area ); |
20 |
console.log( 'Name of Shape: ' + square.name ); |
21 |
console.log( 'Color of Shape: ' + square.color ); |
22 |
console.log( 'Width of Shape: ' + square.width ); |
23 |
console.log( 'Height of Shape: ' + square.height ); |
Вышеуказанный класс Shape
имеет два свойства, area
и color
, один конструктор (точно названный constructor()
), а также метод shoutout()
. Скоуп аргументов конструктора (name
, width
и height
) являются локальными для конструктора. Вот почему вы увидите ошибки в браузере, а также компилятора:
1 |
class.ts(12,42): The property 'name' does not exist on value of type 'Shape' |
2 |
class.ts(20,40): The property 'name' does not exist on value of type 'Shape' |
3 |
class.ts(22,41): The property 'width' does not exist on value of type 'Shape' |
4 |
class.ts(23,42): The property 'height' does not exist on value of type 'Shape' |



Любая программа JavaScript уже является программой TypeScript.
Затем давайте рассмотрим public
и private
модификаторы доступа. Доступ к публичным членам можно получить повсюду, тогда как частные члены доступны только в рамках класса. Разумеется, в JavaScript нет возможности для обеспечения конфиденциальности, поэтому доступность для частного доступа обеспечивается только во время компиляции и служит предупреждением первоначальному намерению разработчика сделать его конфиденциальным.
В качестве иллюстрации добавим модификатор public
к аргументу конструктора, name
и модификатор private
к color
. Когда мы добавляем public
или private
доступность к аргументу конструктора, этот аргумент автоматически становится членом класса с соответствующим модификатором доступности.
1 |
...
|
2 |
private color: string; |
3 |
...
|
4 |
constructor ( public name: string, width: number, height: number ) { |
5 |
...
|



1 |
class.ts(24,41): The property 'color' does not exist on value of type 'Shape' |
Наследование
Наконец, вы можете расширить существующий класс и создать из него производный класс с ключевым словом extends
. Давайте добавим следующий код к существующему файлу class.ts
и скомпилируем его:
1 |
class Shape3D extends Shape { |
2 |
|
3 |
volume: number; |
4 |
|
5 |
constructor ( public name: string, width: number, height: number, length: number ) { |
6 |
super( name, width, height ); |
7 |
this.volume = length * this.area; |
8 |
};
|
9 |
|
10 |
shoutout() { |
11 |
return "I'm " + this.name + " with a volume of " + this.volume + " cm cube."; |
12 |
}
|
13 |
|
14 |
superShout() { |
15 |
return super.shoutout(); |
16 |
}
|
17 |
}
|
18 |
|
19 |
var cube = new Shape3D("cube", 30, 30, 30); |
20 |
console.log( cube.shoutout() ); |
21 |
console.log( cube.superShout() ); |
Несколько вещей происходят с производным классом Shape3D
:
- Поскольку он получен из класса
Shape
, он наследует свойстваarea
иcolor
. - Внутри метода конструктора метод
super
вызывает конструктор базового классаShape
, передавая значенияname
,width
иheight
. Наследование позволяет нам повторно использовать код изShape
, поэтому мы можем легко вычислитьthis.volume
с унаследованным свойствомarea
. - Метод
shoutout()
переопределяет реализацию базового класса, а новый методsuperShout()
напрямую вызывает методbuout()
базового класса, используя ключевое словоsuper
. - Основной сайт
- Учебники и примеры
- Редактор живого кода с выводом JavaScript
- Репозиторий кода для обсуждения и отслеживания ошибок
- Что такое TypeScript?
- Список документации для TypeScript
Имея только несколько дополнительных строк кода, мы можем легко расширить базовый класс, чтобы добавить более конкретные функции и сделать наше намерение известным с помощью TypeScript.



Ресурсы TypeScript
Несмотря на чрезвычайно молодой возраст TypeScript, вы можете найти много полезных ресурсов в Интернете (включая полный курс, который подходит к Tuts + Premium!). Обязательно проверьте их:
Мы только начинаем
TypeScript поддерживает классы, и их реализация тесно соответствует предложению ECMAScript 6.
Попробовать TypeScript легко. Если вам нравится более статически типизированный подход для больших приложений, то функции TypeScript будут применять привычную, дисциплинированную среду. Хотя его и сравнивают с CoffeeScript или Dart, TypeScript отличается тем, что он не заменяет JavaScript; он добавляет функции JavaScript.
Нам еще предстоит увидеть, как будет развиваться TypeScript, но Microsoft заявила, что сохранит свои многочисленные функции (аннотации типов) в соответствии с ECMAScript 6. Итак, если вы хотите попробовать многие новые функции ES6, TypeScript - отличный способ сделать это! Вперед, попробуйте!