Статьи

Начало работы с TypeScript

В конце 2012 года Microsoft представила TypeScript , типизированный надмножество для JavaScript, которое компилируется в простой JavaScript. TypeScript фокусируется на предоставлении полезных инструментов для крупномасштабных приложений путем реализации таких функций, как классы, аннотации типов, наследование, модули и многое другое! В этом руководстве мы начнем с TypeScript, используя простые примеры кода размером с кусочек, компилируем их в JavaScript и просматриваем мгновенные результаты в браузере.


Функции TypeScript применяются только во время компиляции.

Вы настроите свою машину в соответствии с вашей конкретной платформой и потребностями. Пользователи Windows и Visual Studio могут просто загрузить плагин Visual Studio . Если вы работаете в Windows и у вас нет Visual Studio, попробуйте Visual Studio Express для Web . Опыт TypeScript в Visual Studio в настоящее время превосходит другие редакторы кода.

Если вы работаете на другой платформе (или не хотите использовать Visual Studio), все, что вам нужно, — это текстовый редактор, браузер и пакет TypeScript npm для использования TypeScript. Следуйте этим инструкциям по установке:

  1. Установить Node Package Manager (npm)
    1
    2
    3
    $ curl http://npmjs.org/install.sh |
    $ npm —version
    1.1.70
  2. Установите пакет TypeScript npm глобально в командной строке:
    1
    2
    3
    4
    5
    $ npm install -g typescript
    $ npm view typescript version
    npm http GET https://registry.npmjs.org/typescript
    npm http 304 https://registry.npmjs.org/typescript
    0.8.1-1
  3. Любой современный браузер : Chrome используется для этого урока
  4. Любой текстовый редактор: Sublime Text используется для этого урока
  5. Плагин подсветки синтаксиса для текстовых редакторов

Это оно; мы готовы сделать простое приложение » Hello World » на TypeScript!


TypeScript является расширенным набором Ecmascript 5 (ES5) и включает функции, предложенные для ES6. Из-за этого любая JavaScript-программа уже является программой TypeScript. Компилятор TypeScript выполняет преобразования локальных файлов в программах TypeScript. Следовательно, окончательный вывод JavaScript точно соответствует вводу TypeScript.

Сначала мы создадим базовый файл index.html и будем ссылаться на внешний файл скрипта:

01
02
03
04
05
06
07
08
09
10
11
12
<!doctype html>
<html lang=»en»>
<head>
  <meta charset=»UTF-8″>
  <title>Learning TypeScript</title>
</head>
<body>
 
    <script src=»hello.js»></script>
 
</body>
</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.


Типовые аннотации являются дополнительной функцией, которая позволяет нам проверять и выражать свои намерения в программах, которые мы пишем. Давайте создадим простую функцию area() в новом файле TypeScript с именем type.ts

1
2
3
4
5
6
function area(shape: string, width: number, height: number) {
    var area = width * height;
    return «I’m a » + shape + » with an area of » + area + » cm squared.»;
}
 
document.body.innerHTML = area(«rectangle», 30, 15);

Затем измените источник сценария в index.html на type.js и запустите компилятор TypeScript с помощью tsc type.ts Обновите страницу в браузере, и вы должны увидеть следующее:

Как показано в предыдущем коде, аннотации типов выражаются как часть параметров функции; они указывают, какие типы значений вы можете передать функции. Например, параметр shape обозначается как строковое значение, а width и height — числовые значения.

Аннотации типов и другие функции TypeScript применяются только во время компиляции. Если вы передадите эти параметры другим типам значений, компилятор выдаст вам ошибку во время компиляции. Такое поведение чрезвычайно полезно при создании крупномасштабных приложений. Например, давайте нарочно передадим строковое значение для параметра width :

1
2
3
4
5
6
function area(shape: string, width: number, height: number) {
    var area = width * height;
    return «I’m a » + shape + » with an area of » + area + » cm squared.»;
}
 
document.body.innerHTML = area(«rectangle», «width», 15);

Мы знаем, что это приводит к нежелательному результату, и компиляция файла предупреждает нас о проблеме со следующей ошибкой:

1
2
$ tsc type.ts
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 :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
interface Shape {
    name: string;
    width: number;
    height: number;
    color?: string;
}
 
function area(shape : Shape) {
    var area = shape.width * shape.height;
    return «I’m » + shape.name + » with area » + area + » cm squared»;
}
 
console.log( area( {name: «rectangle», width: 30, height: 15} ) );
console.log( area( {name: «square», width: 30, height: 30, color: «blue»} ) );

Интерфейсы — это имена, данные типам объектов. Мы можем не только объявить интерфейс, но и использовать его как аннотацию типа.

Компиляция interface.js приводит к ошибкам. Чтобы вызвать ошибку, давайте добавим еще одну строку кода в interface.js с формой, у которой нет свойства name, и просмотрим результат в консоли браузера. Добавьте эту строку в interface.js :

1
console.log( area( {width: 30, height: 15} ) );

Теперь скомпилируйте код с помощью tsc interface.js . Вы получите ошибку, но не беспокойтесь об этом прямо сейчас. Обновите ваш браузер и посмотрите на консоль. Вы увидите нечто похожее на следующий скриншот:

Теперь давайте посмотрим на ошибку. Это:

1
2
interface.ts(26,13): Supplied parameters do not match any signature of call target:
Could not apply type ‘Shape’ to argument 1, which is of type ‘{ width: number;

Мы видим эту ошибку, потому что объект, переданный в area() , не соответствует интерфейсу Shape ; для этого нужно свойство name.


Понимание области действия this ключевого слова является сложной задачей, и TypeScript делает его немного проще, поддерживая выражения функций стрелок, новую функцию, обсуждаемую для ECMAScript 6 . Функции со стрелками сохраняют значение this , что значительно упрощает написание и использование функций обратного вызова. Рассмотрим следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
var shape = {
    name: «rectangle»,
    popup: function() {
 
        console.log(‘This inside popup(): ‘ + this.name);
 
        setTimeout(function() {
            console.log(‘This inside setTimeout(): ‘ + this.name);
            console.log(«I’m a » + this.name + «!»);
        }, 3000);
 
    }
};
 
shape.popup();

this.name в строке семь будет явно пустым, как показано в консоли браузера:

Мы можем легко решить эту проблему, используя функцию стрелки TypeScript. Просто замените function() на () => .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
var shape = {
    name: «rectangle»,
    popup: function() {
 
        console.log(‘This inside popup(): ‘ + this.name);
 
        setTimeout( () => {
            console.log(‘This inside setTimeout(): ‘ + this.name);
            console.log(«I’m a » + this.name + «!»);
        }, 3000);
 
    }
};
 
shape.popup();

И результаты:

Взгляните на сгенерированный файл JavaScript. Вы увидите, что компилятор ввел новую переменную, var _this = this; и использовал его в функции обратного вызова setTimeout() для ссылки на свойство name .


TypeScript поддерживает классы, и их реализация тесно следует предложению ECMAScript 6 . Давайте создадим другой файл с именем class.ts и рассмотрим синтаксис класса:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Shape {
 
    area: number;
    color: string;
 
    constructor ( name: string, width: number, height: number ) {
        this.area = width * height;
        this.color = «pink»;
    };
 
    shoutout() {
        return «I’m » + this.color + » » + this.name + » with an area of » + this.area + » cm squared.»;
    }
}
 
var square = new Shape(«square», 30, 30);
 
console.log( square.shoutout() );
console.log( ‘Area of Shape: ‘ + square.area );
console.log( ‘Name of Shape: ‘ + square.name );
console.log( ‘Color of Shape: ‘ + square.color );
console.log( ‘Width of Shape: ‘ + square.width );
console.log( ‘Height of Shape: ‘ + square.height );

Приведенный выше класс Shape имеет два свойства, area и color , один конструктор (метко названный constructor() ), а также метод shoutout() . Область действия аргументов конструктора ( name , width и height ) является локальной для конструктора. Вот почему вы увидите ошибки как в браузере, так и в компиляторе:

1
2
3
4
class.ts(12,42): The property ‘name’ does not exist on value of type ‘Shape’
class.ts(20,40): The property ‘name’ does not exist on value of type ‘Shape’
class.ts(22,41): The property ‘width’ does not exist on value of type ‘Shape’
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
3
4
5
private color: string;
constructor ( public name: string, width: number, height: number ) {
1
class.ts(24,41): The property ‘color’ does not exist on value of type ‘Shape’

Наконец, вы можете расширить существующий класс и создать из него производный класс с помощью ключевого слова extends . Давайте добавим следующий код в существующий файл class.ts и скомпилируем его:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
class Shape3D extends Shape {
 
    volume: number;
 
    constructor ( public name: string, width: number, height: number, length: number ) {
        super( name, width, height );
        this.volume = length * this.area;
    };
 
    shoutout() {
        return «I’m » + this.name + » with a volume of » + this.volume + » cm cube.»;
    }
 
    superShout() {
        return super.shoutout();
    }
}
 
var cube = new Shape3D(«cube», 30, 30, 30);
console.log( cube.shoutout() );
console.log( cube.superShout() );

С производным классом Shape3D происходит несколько вещей:

  • Поскольку он является производным от класса Shape , он наследует свойства area и color .
  • Внутри метода конструктора super метод вызывает конструктор базового класса Shape , передавая значения name , width и height . Наследование позволяет нам повторно использовать код из Shape , поэтому мы можем легко вычислить this.volume с помощью унаследованного свойства area .
  • Метод shoutout() переопределяет реализацию базового класса, а новый метод superShout() напрямую вызывает метод superShout() базового класса с помощью ключевого слова super .
    • Имея всего несколько дополнительных строк кода, мы можем легко расширить базовый класс, чтобы добавить более специфическую функциональность и сделать наше намерение известным через TypeScript.


      Несмотря на очень молодой возраст TypeScript, вы можете найти множество отличных ресурсов по языку в Интернете (включая полный курс, посвященный Tuts + Premium! ). Не забудьте проверить это:


      TypeScript поддерживает классы, и их реализация тесно следует предложению ECMAScript 6 .

      Пробовать TypeScript легко. Если вам нравится более статически типизированный подход для больших приложений, то функции TypeScript обеспечат знакомую дисциплинированную среду. Хотя он сравнивался с CoffeeScript или Dart , TypeScript отличается тем, что он не заменяет JavaScript; это добавляет функции в JavaScript.

      Мы еще не увидели, как будет развиваться TypeScript, но Microsoft заявила, что они сохранят свои многочисленные функции (кроме аннотаций типов) в соответствии с ECMAScript 6. Итак, если вы хотите опробовать многие из новых функций ES6, TypeScript отличный способ сделать это! Вперед, попробуй это!