Разработка веб-сайтов
JavaScript
Программирование
Visual Studio
TypeScript
5 декабря 2014

Анонс новых возможностей Typescript 1.4

Автор оригинала: Ryan Cavanaugh
Перевод
Выпустив версию Typescript 1.3, мы сфокусировались на усовершенствовании системы типов и добавлении функционала ECMAScript 6 в TypeScript. Давайте рассмотрим некоторые новые возможности, которыми вы сможете пользоваться в новой версии.

Все описанные в статье вещи уже реализованы в мастер-ветке нашего репозитория на Github — вы можете выкачать ее и попробовать их уже сейчас.



Новые возможности позволяют более аккуратно и легко работать с переменными, которые имеют различный тип во время исполнения. Они сокращают количество мест, где нужно явно указывать тип, проверять его или использовать тип any. Авторы типизирующих файлов (.d.ts) могут также использовать эти возможности для описания внешних библиотек. Те, кто следят за развитием компилятора, могли заметить, что мы сами тоже ими пользуемся.

Типы-объединения


Общие сведения


Типы-объединения — это мощный способ выразить значение, которое может иметь один из нескольких типов. Допустим, у вас может быть API для выполнения программы, который принимает аргументы командной строки в виде string или string[]. Теперь можно написать так:

interface RunOptions {
  program: string;
  commandline: string[]|string;
}

Присвоение значений такого типа работает интуитивно — любое значение, которое можно было бы присвоить любому из членов перечисления, сработает:

var opts: RunOptions = /* ... */;
opts.commandline = '-hello world'; // OK
opts.commandline = ['-hello', 'world']; // OK
opts.commandline = [42]; // Ошибка: тип number не совместим с string или string[]

При обращении к переменной, можно напрямую использовать свойства, которые являются общими для всех типов в объединении:

if(opts.commandline.length === 0) { // У string и string[] есть свойство length
  console.log("Пусто!");
}

С помощью ограничителей типов, работать с переменной типа-объединения легко и просто:

function formatCommandline(c: string[]|string) {
  if(typeof c === 'string') {
    return c.trim();
  } else {
    return c.join(' ');
  }
}

Ограничители типов


Распространенная практика в Javascript — использовать операторы typeof или instanceof для определения типа значения во время исполнения. Typescript теперь понимает эти конструкции и использует их при выводе типа, если они используются в блоке условия:

var x: any = /* ... */;
if(typeof x === 'string') {
   console.log(x.subtr(1)); // Ошибка: в типе 'string' нет метода 'subtr'
}
// в этой области видимости переменная 'x' все еще типа 'any'
x.unknown(); // OK

Вот так можно пользоваться instanceof с классами и объединенными типами:

class Dog { woof() { } }
class Cat { meow() { } }
var pet: Dog|Cat = /* ... */;
if(pet instanceof Dog) {
   pet.woof(); // OK
} else {
   pet.woof(); // Error
}

Более строгие обобщенные типы


Мы также решили сделать проверку обобщенных вызовов более строгой в некоторых случаях. Например, раньше такой код, как ни странно, компилировался без ошибок:

function equal<T>(lhs: T, rhs: T): boolean {
   return lhs === rhs;
}

// Раньше: никаких ошибок
// Новое поведение: Ошибка - нет общего типа между 'number' и 'string'
var e = equal(42, 'hello');

Улучшенный вывод типов


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

var x = [1, 'world']; // x: Array<string|number>
x[0] = 'hello'; // OK
x[0] = false; // Ошибка - тип 'boolean' не является ни 'number', ни 'string'

Псевдонимы для типов


Можно объявить псевдоним для типа с помощью ключевого слова type:

type PrimitiveArray = Array<string|number|boolean>;
type MyNumber = number;
type NgScope = ng.IScope;
type Callback = () => void;

Псевдоним типа является его полным синонимом, они полностью взаимозаменяемы при использовании.

В следующей статье я расскажу о возможностях ECMAScript 6, которые мы добавляем в Typescript. Чтобы узнать больше и попробовать самому, выкачайте ветку master из репозитория Typescript на Github, попробуйте и поделитесь с нами.

Примечание переводчика



В Typescript 1.3 появилась возможность использовать кортежи из массивов. Однако автоматический вывод типов при этом не происходит:

// ожидается: [number, string]
// фактически будет: Array<string|number>
var x = [1, 'world'];

Почему так сделали? Автоматический вывод типов-кортежей ломает множество сценариев использования, например:

var x = [dog, cat, animal]; // тип для 'x' будет 'Animal[]'
x[0] = new Frog();

Если бы тип переменной x был выведен как кортеж [Dog, Cat, Animal], то присвоение во второй строке вызвало бы ошибку. Авторы посчитали более правильным требовать явного указания кортежей, и это звучит довольно логично.

Кроме того, кортежи совместимы с типами-перечислениями в одностороннем порядке:
var x : [number, string] = [1, "test"];
var y : Array<number|string> = x; // Все в порядке
x = y; // ошибка: типы совместимы только в одну сторону

Скорее бы поддержка этих возможностей попала в Resharper!

UPD: Не пора ли создать отдельный хаб под Typescript?
Используете ли вы Typescript?
18.6% Да, вместе с другими продуктами Microsoft (Visual Studio, .NET) 101
9.7% Да, в Linux / Mac OS / другой системе 53
34.9% Хотел бы попробовать, но пока не доходят руки 190
9.7% Использую другие препроцессоры (CoffeeScript, LiveScript) 53
18.2% Препроцессоры зло, только нативный Javascript! 99
8.6% Не пишу ни на JS, ни на чем подобном 47
Проголосовали 543 пользователя. Воздержались 87 пользователей.
+22
12,4k 53
Комментарии 39
Популярное за сутки