Релиз TypeScript 1.6: не только React

    Компания Microsoft активно выпускает новые версии TypeScript. Товарищи разработчики объявили о выпуске бета версии TS версии 1.6 аж второго сентября. А уже 16 сентября был выпущен релиз. Скоростные ребята. Но при этом релиз как-то прошел незамеченным (не для всех, но все же). На Хабре как-то не было упоминаний (я не нашел). А посему немного информации по улучшениям.

    Одна из мощных фич этой версии заключается в нативной поддержке синтаксиса React/JSX. Но это не все. Вот перечень некоторых нововведений:

    • Генераторы ES6
    • Локальные типы
    • Алиасы на генерик типы
    • Классовые выражения (анонимные классы)
    • Поддержка JSX
    • Абстрактные классы и методы
    • Новый флаг –init
    • Новая секция “exclude” в конфигурационном файле tsconfig.json

    Рассмотрим наиболее интересные из них. Го под кат, если интересно.

    Весь перечень нововведений можно увидеть на официальной странице.

    Генераторы ES6


    Тут все просто – можно теперь писать функции генераторы. Их можно типизировать, естественно. Интерфейс генератора выглядит так:

    interface Generator<TYield, TReturn, TNext> extends IterableIterator<TYield /*| TReturn*/> {
        next(n: TNext): IteratorResult<TYield /*|TReturn*/>;
        // throw and return methods elided
    }
    

    Пример использования:

    
    interface Generator<TYield, TReturn, TNext> extends IterableIterator<TYield | TReturn> {
       next(n: TNext): IteratorResult<TYield | TReturn>;
    }
    
    
    function *g(): Generator<number, any, string> {
       let x = yield 0; // x имеет тип string
    }
    
    

    Больше примеров можно найти по ссылке github.com/Microsoft/TypeScript/issues/2873

    Локальные типы


    Еще одно интересное нововведение – локальные типы. Теперь можно объявлять типы внутри условий, что расширяет возможности для мета программирования. Пример:

    
    function f() {
       if (true) {
          interface T { x: number }
          let v: T;
          v.x = 5;
       }
       else {
          interface T { x: string }
          let v: T;
          v.x = "hello";
       }
    }
     
    

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

    
    function f() {
       enum E {
          A, B, C
       }
       class C {
          x: E;
       }
       interface I {
          x: E;
       }
       type A = I[];
       let a: A = [new C()];
       a[0].x = E.B;
    }
    
    

    Больше примеров можно найти по ссылке github.com/Microsoft/TypeScript/pull/3266

    Алиасы для генериков


    Новая возможность позволяет задавать псевдонимы на генерики. Пример кода:

    
    type Source<T> = T | (() => T);
    
    function unwrap<T>(p: Source<T>) {
       return (typeof p === "function") ? p() : p;
    }
    

    Больше примеров можно найти по ссылке github.com/Microsoft/TypeScript/issues/1616

    Class expressions


    У нас всегда была возможность объявлять классы. Теперь есть возможность описывать классовые выражения. Такие выражения представляют из себя анонимные классы, по аналогии с анонимными функциями. Пример кода:

    
    var Rect = class {
       area: number;
    
       constructor(public length: number, public width: number) {
          this.area = this.length * this.width;
       }
    }
    
    var rect = new Rect(5, 10);
    
    var MyNode = class Node {
       next: Node;
       set nextNode(node: Node) {
          this.next = node;
       }
       constructor() {}
    }
    
    var node = new MyNode();
    var nextNode = new MyNode();
    node.nextNode = nextNode;
    
    

    Абстрактные классы


    Тут все просто. У нас появилось ключевое слово abstract, которое, как и в других языках программирования, ставится перед определением класса и/или метода. В итоге мы можем объявить класс с реализацией, но от него нельзя создавать экзмепляры объектов.

    
    type int = number;
    
    abstract class A {
       foo(): int { return bar(); }
       abstract bar() : int;
    }
    
    class B extends A {
       bar() {
          return 42;
       }
    }
    
    new A(); // Error!
    new B(); // OK
    
    

    User defined type guard functions


    Это интересная синтаксическая конструкция, которая позволяет описывать функции проверки без дополнительных условий. Примеры:

    function isCat(a: Animal): a is Cat {
       return a.name === 'kitty';
    }
    
    var x: Animal;
    
    if(isCat(x)) {
       x.meow(); // OK, x is Cat in this block
    }
    
    

    React/JSX = TSX


    В компиялторе появилась новая опция --jsx react. Если она указана, то происходит транспилирование JSX синтаксиса прямо в TS файлах. Точнее даже TSX (по аналогии с JSX). Пример такого кода:

    
    export interface ITodoItemState {}
    
    export interface ITodoItemProps {
       item: ITodo;
       onRemove?: (todo: ITodo) => any;
       key?: number;
    }
    
    export class TodoItem extends React.Component<ITodoItemProps, ITodoItemState> {
       constructor () {
          super();
          this.removeItem = this.removeItem.bind(this);
       }
    
       removeItem () {
          this.props.onRemove(this.props.item);
       }
    
       render () {
          return (
             <li>
                <span> {this.props.item.description} </span>
                   <button onClick={this.removeItem} >delete</button>
             </li>
          );
       }
    }
    
    

    До сегодняшнего дня, чтобы разрабатывать на React+TypeScript, приходилось использовать либо React templates (что мы и делаем в Tutu.ru), либо вовсе отказаться от JSX синтаксиса. Но теперь у нас появляется возможность использования JSX, что называется, из коробки. Любителям React это должно понравиться.

    Есть два режима работы:
    • --jsx preserve — на выходе получаем JSX
    • --jsx react — на выходе получаем обработанный JS

    А вообще получилась хорошая альтернатива бабелю. Я бы даже сказал что конкуренция (в некоторых вещах). Если вы используете BabelJS + Flow, то посмотрите на TS. Он для энтерпрайза больше подходит. Но это мое имхо, так что на вкус и цвет.
    Метки:
    Поделиться публикацией
    Комментарии 13
    • 0
      С генераторами есть некоторая засада: они поддерживаются только если компиляция идет в ES6. То есть для старых версий nodejs и для старых браузеров придется (пока) без них. Babel умеет транспилить генераторы в ES5, а TS — нет.
      • 0
        Если прям нужны генераторы, то да, засада. Либо ставим флаги на ноде/iojs. Либо генераторы отдельно транспилим еще и бабелем.
        • +1
          Мне лично нет, да и вообще жили же мы без генераторов. Я просто предупреждаю, потому что засада неочевидная.
        • +2
          Можно компилировать в ES6 и дополнительно babel-ем транспайлить в ES5. Я пока так и делаю, хотя попахивает извращением — но куда деваться :-)
          • 0
            Да почему, typescript это расширение стандарта и главная задача компилятора typescript сделать из нестандартного кода стандартный (хотя компилятор имеет небольшое количество фич es6 -> es5, их добавляют аккуратно).

            Babel же это инструмент задача которого из кода написанного по стандарту es2015 сделать код совместимый с предыдущем стандартом, так что выглядит всё корректно.
            • +2
              К слову, не только es2015, тем ещё есть поддержка драфтов es7, jsx и flow. Последние два прямо из-коробки, без каких-либо доп.опций.
          • +3
            Babel тоже сам генераторы не компилирует, а использует regenerator. Никто не мешает использовать regenerator и с TypeScript.
          • 0
            Никто не знает, когда они планирует декораторы сделать стандартной фичей, а не экспериментальной?
            • 0
              Сам жду. Хотя даже сейчас уже работают в целом ок. Сам код декораторов на выходе не такой сложный получается. Так что используя в экспериментальном режиме можно контролировать результат. Разве что именно результирующий код будет меняться.
            • 0
              Компания Microsoft активно выпускает новые версии своего диалекта JavaScript

              Ну тут наверное компания Microsoft активно с вами не согласиться, TS не диалект а полноценный язык да еще и надмножество над самим JS.
              • 0
                Ок, дабы исправить холивар, сделаю UPD
                • 0
                  Я вовсе не думал о холиваре, честно. Просто изначально MS подошла к TS очень серьезно, вы посмотрите кто спроектировал язык. Вообще радует такой букет фич в новых релизах, да и дорожная карта просто пестрит. Очень продуманно создатели подходят к реализации языка, для меня это один из лучших проектов MS за последние лет пять.
                  • 0
                    Я никак не оспариваю крутость и великолепие языка TS. Но вспомните как они сами его называют: TS — это JS. Иногда говорят: это язык расширяющий возможности JavaScript. Любые расширения и отхождения от оригинального языка — это диалект.

                    Что есть диалект:
                    Диале́кт (греч. διάλεκτος — «наречие») — разновидность языка, связанная с оригиналом одной территорией.


                    MS выпустил диалект языка JavaScript. Так что говоря слово диалект я строю конгруэнтное предложение и не вижу в этом противоречий.

                    Резюмируя: TS — это полноценный язык, все верно, так как не может быть другого определения иначе оно будет противорчить. А полноценный язык потому, что TS — это JS с расширением.

                    И в заключении своей тирады: мне очень нравится TS и за него респект и уважение компании MS.

              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.