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

в 10:42, , рубрики: compiler, javascript, TypeScript, Visual Studio, Веб-разработка, компилятор, Программирование

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

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

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

Новые возможности позволяют более аккуратно и легко работать с переменными, которые имеют различный тип во время исполнения. Они сокращают количество мест, где нужно явно указывать тип, проверять его или использовать тип 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?

Автор: impwx

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js