КатегорииTypeScript

TypeScript: Урок 1 — Основные моменты

JavaScript — по настоящему вездесущий язык программирования. Можно написать веб приложение причем не только frontend, но и backend используя Node.js. И это не все, можно использовать Apache Cordova или ReactNative и другие подобные технологии для написания мобильных приложений , а можно программировать микроконтроллеры используя Kinoma. Бесспорный факт, что JavaScript завоевал популярность и используется практически на любой платформе. 

Как у любого языка программирования, у него есть плюсы и минусы. Он достаточно прост в изучении, изначально он был создан для создания простых быстрых скриптов, сомневаюсь, что создатели могли предположить, что на нем будут писать большие приложения и огромным количеством кода. И вот с созданием больших, надежных приложений на JavaScript все не так здорово, как хотелось бы:

JavaScript — интерпретируемый язык из-за чего мы можем узнать о проблеме (например опечатке), только после выполнения кода, что не очень удобно.

JavaScript — язык прототипов, то бишь не объектно-ориентированный. Что подразумевает другую концепцию работы с объектами, и сложности использования проверенных практик объектно-ориентированного программирования.

JavaScript — динамическая типизация, то тоже доставляет немало головной боли, с проверками на тип значения.

TypeScript — призван помочь решить эти проблемы.  Это строго типизированный объектно-ориентированных язык, который компилируется в JavaScript. Он позволяет использовать хорошо известные практики и шаблоны объектно-ориентированного программирования, а так же проверяет код на этапе компиляции. Полученный JavaScript может выполнять в любой среде в которой работает JavaScript, то есть это самый обычный JavaScript.

Введение

TypeScript — это не только язык программирования но и еще набор инструментов для генерации JavaScript. Он был разработан Андерсом Хейльсбергом (создатель C#) и является проектом с открытым исходным кодом, главной целью которого является помочь нам в создании больших и надежных приложений на JavaScript.

Преимущества TypeScript

Чтобы подчеркнуть преимущества TypeScript (и это далеко не полный список), давайте очень быстро рассмотрим некоторые вещи:

  • Компиляция
  • Строгая типизация
  • Использование популярных библиотек JavaScript
  • Инкапсуляция
  • Скрытые и публичные свойства и методы класса.

Компиляция

Одна из неприятностей которую можно встретить при разработке на JavaScript — это опечатка или случайное переопределение глобальной переменной. Что можно обнаружить только на этапе выполнения программы. И это явно не экономит время разработки.

TypeScript при компиляции проверяет код на ошибки, что очевидно ускорит выявление подобных неприятностей.

Строгая типизация

JavaScript не строго типизирован. Он очень динамичен и поэтому позволяет объектам изменять свои свойства «на лету». В качестве примера рассмотрим следующий код:

let test = "это строка"; 
test = 1; 
test = function(a, b) { 
    return a + b; 
}

Тут переменная test сначала становиться строкой, потом числом и наконец функцией. Однако в традиционных объектно-ориентированных языках такой фокус не пройдет, потому их и называют строго типизированными.

Хотя весь предыдущий код является допустимым JavaScript и поэтому может быть оправданным, и все же довольно легко понять, как это может привести к ошибкам во время выполнения. Такие ошибка легко выявлять в небольшом количестве кода, но с его ростом и ростом количества разработчиков все становиться не так просто.

Еще одна особенность строгой типизации заключается в том, что IDE, в которой вы работаете, понимает, с какой переменной вы работаете, и может предложить лучший вариант автозаполнение или Intellisense.

Синтаксический сахар TypeScript

TypeScript вводит очень простой синтаксис для проверки типа объекта во время компиляции. Этот синтаксис упоминается как «синтаксический сахар» или более формально, аннотации типа. Рассмотрим следующий код TypeScript:

let test:string = "this is a string"; 
test = 1; 
test = function(a, b) { return a + b; }

Обратите внимание при объявлении переменной test следом идет : и string, что означает что переменная test имеет тип string. И любой код который пытается использовать переменную test не как строку генерирует ошибку компиляции. Запуск кода выше выдаст следующие ошибки:

hello.ts(3,1): error TS2322: Type 'number' is not assignable to type 'string'.
hello.ts(4,1): error TS2322: Type '(a: any, b: any) => any' is not assignable to type 'string'.

Первая ошибка довольно очевидная. Мы указали, что переменная test является строкой, а затем пытаемся присвоить в нее число, что понятно из описания ошибки. Вторая похожа на первую, и, по сути, говорит о том, что мы не можем назначить строковой переменной функцию.

Таким образом, компилятор TypeScript вводит строгую типизацию в ваш код JavaScript, предоставляя вам все преимущества строго типизированного языка. Поэтому TypeScript описывается как надмножество JavaScript.

Использование популярных библиотек JavaScript

Предположим у нас есть библиотека JavaScript, как ее можно использовать в TypeScript? Ответ достаточно прост — создать файл определения. TypeScript использует файл с расширением .d.ts, как своего рода заголовочный файл С++. Такой файл содержит информацию, которая описывает каждую доступную функцию и / или переменную вместе с аннотациями связанных с ними типов.

Давайте рассмотрим на примере функции describe популярной библиотеки модульного тестирования Jasmine:

var describe = function(description, specDefinitions) { 
    return jasmine.getEnv().describe(description, specDefinitions); 
};

Обратите внимание, что эта функция имеет два параметра description и specDefinitions. К сожалению, JavaScript не говорит нам, что за тип скрывается за ними. Нам нужно взглянуть на документацию, чтобы выяснить ожидаемые типы. Если мы перейдем к http://jasmine.github.io/2.0/introduction.html , мы увидим пример использования этой функции:

describe("A suite", function () { 
   it("contains spec with an expectation", function () { 
     expect(true).toBe(true); 
   }); 
});

Из этого можно сделать выводы description имеет строковый тип,  а specDefinitions это функция, следование чтобы использовать данную функцию в TypeScript надо создать jasmine.d.ts:

declare function describe( 
  description: string,  
  specDefinitions: () => void 
): void;

Если мы попробуем передать параметры наоборот:

describe(() => { /* function body */}, "description");

TypeScript генерирует следующую ошибку:

hello.ts(11,11): error TS2345: Argument of type '() => void' is not assignable to parameter of type 'string'.

Из ошибки видно, что мы пытаемся вызвать функцию с неверными параметрами. В следующих уроках мы подробно рассмотрим файл определения типов.

DefinitelyTyped

Вскоре после выпуска TypeScript Борис Янков создал репозиторий GitHub для размещения файлов определения типов, с названием DefinitelyTyped ( http://definitelytyped.org). Этот репозиторий теперь стал основным местом для поиска файлов определений типов для интеграции внешних библиотек JavaScript в TypeScript, и в настоящее время он содержит определения для более 1600 библиотек JavaScript.

Инкапсуляция

Одним из фундаментальных принципов объектно-ориентированного программирования является инкапсуляция — способность определить данные, а также набор функций. которые могут работать с этими данными, в один компонент. Большинство языков программирования имеют концепцию классов для этой цели.

Для начала рассмотрим простейшее определение класса TypeScript:

class MyClass { 
  add(x, y) { 
    return x + y; 
  } 
} 
 
let classInstance = new MyClass(); 
let result = classInstance.add(1,2); 
console.log(`add(1,2) returns ${result}`);

Этот код достаточно прост для чтения и понимания. Мы создали класс, называли его MyClass, с простой функцией add. Чтобы использовать этот класс, мы просто создаем его экземпляр и вызываем функцию add с двумя аргументами. JavaScript, к сожалению. не имел до ES6 инструкцию класса. Но даже сейчас с приходом ES6 у JavaScript нет еще одной особенности инкапсуляции — области видимости членов класса.

Скрытые и публичные члены класса

Еще одним объектно-ориентированным принципом. который используется в инкапсуляции, является концепция скрытых данных  — способность иметь общедоступные или частные переменные. Частные переменные предназначены для скрытия от пользователя внутренней кухни класса, то бишь используются только для внутреннего пользования. Непреднамеренное изменение этих переменных может привести к ошибкам во время выполнения.

К сожалению, JavaScript не имеет собственного способа объявлять частные переменные. Хотя эту функциональность можно эмулировать с помощью замыкания, а так же многие программисты JavaScript просто используют символ подчеркивания _ для обозначения частной переменной . Однако если вы знаете имя частной переменной, вы можете легко присвоить ей значение. Рассмотрим следующий код JavaScript:

var MyClass = (function() { 
    function MyClass() { 
        this._count = 0; 
    } 
    MyClass.prototype.countUp = function() { 
        this._count ++; 
    } 
    MyClass.prototype.getCountUp = function() { 
        return this._count; 
    } 
    return MyClass; 
}()); 

var test = new MyClass(); 
test._count = 17; 
console.log("countUp : " + test.getCountUp());

В результате в консоле мы увидим countUp: 17. Что вообще не желательно.

В TypeScript есть возможность строго обозначить доступ к членам класса с помощью ключевых слов public и private. Пытаясь получить доступ к приватному члену обозначенному как private будет выдана ошибка времени компиляции. В качестве примера давайте посмотрим на следующий код:

class CountClass { 
    private _count: number; 
    constructor() { 
        this._count = 0; 
    } 
    countUp() { 
    this._count ++; 
    } 
    getCount() { 
    return this._count; 
    } 
} 
var countInstance = new CountClass() ; 
countInstance._count = 17; 
console.log("countUp : " + test.getCountUp());

Тут _count имеет модификатор private, что не позволит изменить его за пределами класса на прямую. Запустив этот код мы получим ошибку:

hello.ts(39,15): error TS2341: Property '_count' is private and only
accessible within class 'CountClass'.

Такая возможность позволяет избежать ошибок еще на этапе компиляции, что не может не радовать.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *