Три ключевые новые вещи, которые мы добавляем в инструменты TypeScript: более богатый опыт работы с ES6, декораторы и новый плагин для Sublime Text.
Вы можете попробовать альфа-версию сегодня, установив новый компилятор через npm.
Улучшенный опыт работы с ES6
В TypeScript 1.5 мы добавили несколько новых возможностей ES6. Эти возможности мы связали с системой типов TypeScript, чтобы дать вам дополнительную поддержку в инструментах при работе с новыми шаблонами написания кода, присущими ES6.
Модули
Синтаксис модулей в ES6 — это мощный путь для работы с модулями. Вы можете взаимодействовать с ними, импортируя модуль целиком или работая с отдельными импортируемыми сущностями.
import * as Math from "my/math";
import { add, subtract } from "my/math";
ES6 также поддерживает ряд возможностей для указания экспоритуемых элементов. Вы можете выставлять такие декларации, как классы или функции. Вы также можете экспортировать «default», чтобы импортировать из модуля напрямую. Например:
// math.ts
export function add(x, y) { return x + y }
export function subtract(x, y) { return x – y }
export default function multiply(x, y) { return x * y }
// myFile.ts
import {add, subtract} from "math";
import times from "math";
var result = times(add(2, 3), subtract(5, 3));
Если вы уже использовали TypeScript, вы можете заметить, что это очень похоже на собственные внешние модули TypeScript. Это не случайность: когда мы создавали синтаксис внешних модулей в TS, мы работали над теми же сами проблемами. Однако дизайн ES6 расширяет эти возможности еще дальше, демонстрируя мощный и зрелый дизайн. Мы продолжим поддерживать внешние модули TS, но при этом призываем разработчиков начать использовать более мощный синтаксис модулей из ES6.
Деструктурирование
Деструктурирование (destructuring) — это удобная новая возможность, которая появляется в TS как часть нашей поддержки стандарта ES6. С его помощью вы можете разделять или разрушать объекты и массивы.
var [x, y] = [10, 20];
[x, y] = [y, x]; // a simple swap
Вы можете также использовать разрушение для управления параметрами функции:
var myClient = {name: "Bob", height: 6};
function greetClient({name, height: howTall}) {
console.log("Hello, " + name + ", who is " + howTall + " feet tall.");
}
greetClient(myClient);
В примере выше функция greetClient принимает единый объект со свойствами name и height. Используя синтаксис 'height: howTall', мы можем переименовать своейство height в howTall внутри greetClient.
И еще...
Мы также добавили поддержку for-of для улучшения итераций, компиляцию let/const в ES5, поддержку юникода, режим выдачи ES6-кода и внедрили улучшения в поддержке вычисляемых свойств.
Декораторы
Мы работаем с командами Angular, Ember и Aurelia (от создателей Durandal) над предложением по декораторам в ES7, превью которых мы добавили в альфа-версию TypeScript 1.5. Декораторы позволяют вам четко указывать особенности кода. В примере ниже мы видим, как декоратор @memoize может быть использован для обозначения, что пара геттера и сеттера может быть мемоизирована:
class Person {
@memoize
get name() { return `${this.first} ${this.last}` }
set name(val) {
let [first, last] = val.split(' ');
this.first = first;
this.last = last;
}
}
Разработчики смогут создавать новые декораторы и смешивать их при работе с системой типов.
Плагин для Sublime Text
Вместе с альфа-версией TypeScript 1.5 мы также выпускаем превью плагина для Sublime Text для работы с TypeScript, чтобы у тех разработчиков, которые пользуются данным редактором, также была возможность работать с TypeScript. Этот плагин работает как с Sublime Text 2, так и с Sublime Text 3 и дает возможность почувствовать, какие преимущества дает система типов из TypeScript. Sublime Text и плагин TypeScript доступны для OSX, Linux и Windows.
Команды TypeScript, доступные в Sublime Text
Плагин для Sublime Text позволяет вам легко перемещаться по коду, осуществлять рефакторинг, форматирование и исследование кода. Для тех, кто пробовал плагин, который был показан во время демонстрации на ng-conf, обновленный плагин покажется заметно более шустрым, особенно на больших файлах.
Мы будем рады услышать ваши отзывы. Если вы хотите оставить комментарий, расскажите о проблеме в трекере на GitHub. Также не стесняйтесь и отправляйте нам ваши предложения через запрос на включение, чтобы вместе сделать плагин для Sublime еще лучше.
Что дальше
Данная альфа-версия показывает, что будет возможным делать на TypeScript 1.5, когда он будет выпущен, — и мы очень хотим узнать, что вы об этом думаете. Мы активно работаем над TS1.5 — и вы можете помочь нам сделать этот релиз лучше, пробуя его и рассказывая нам о любых проблемах, с которыми вы столкнетесь.
Комментарии (28)
dom1n1k
03.04.2015 17:14-1Прочитал недавно всю спецификацию — в целом язык понравился.
Правда, создалось ощущение, что полезен он будет только в режиме «полного цикла» — то есть когда на нем пишется большой проект, целиком от начала до конца.
Писать на нем, например, библиотеку общего назначения вроде как бессмысленно.kichik Автор
03.04.2015 17:22Ну для библиотеки как раз это имеет большой смысл в двух аспектах: проектирование API и выставление его наружу с подсказками для редактора через .d.ts.
Вот пример ребят из Wix: blogs.msdn.com/b/typescript/archive/2015/03/17/guest-post-gil-amran-talks-about-using-typescript-at-wix.aspx. Внутренние функции хоть на голом JS, а на стыках TS.dom1n1k
03.04.2015 17:27Про .d.ts знаю, но это для других пользователей TS.
А я другое имел в виду: писать на TS библиотеку, которую потом будут использовать разные люди, пишущие в других окружениях (ванильный JS, CS, LS и пр). В этом случае особо большого смысла не видно.
Vestild
03.04.2015 17:24-1Если к библиотеке идёт .d.ts файл, это сильно облегчает её понимание. Это так, на всякий случай.
impwx
03.04.2015 17:44-1Почему же, очень практично. Исходный код библиотеки будет на TS со всеми плюшками, а все остальные могут использовать скомпилированный js-вариант. Примерно так команды Angularjs \ Ember \ остальных фреймворков и работают.
btd
03.04.2015 19:17+1Я может быть не в тему. Я видел в ts репозитории issue на добавление типов числе переменной длины (i8 — int8, uint, int и тд). Не знаете, планируется что нибудь такое добавить. Понятно, что это здоровенный костыль в js, но сделало бы типобезопасную работу проще с битовыми операциями.
И я даже очень понимаю насколько это не популярно, и может понадобится весьма не часто. Но просто реальных альтернатив я не нашел, самое близкое это asm.js — но его руками не напишешь.Eternalko
04.04.2015 17:50Почему костыль? Разработчики на JS уже давно используют типизацию на полную катушку.
Там где есть необходимость.
Вот тут можно ознакомиться с фундаментом: Typed Array.
Есть полно библиотек которые добавляют сахару (удобства) использования.
asm.js, кстати, тоже через них работает.btd
04.04.2015 19:06Костыль потому что в яваскрипте самом нет такой типизации. А что я хочу я думаю лучше объяснить на примере:
let a: int8 = 150
let b: int8 = 200
Я хочу чтобы в результате было для
a | b
(a | b) & 0xFFEternalko
04.04.2015 20:52+1var a, b, c, typed; typed = new Uint8Array(new ArrayBuffer(2)); typed[0] = 150; typed[1] = 200; typed[2] = 300; // # undefined. Only 2 bytes allocated a = typed[0] | typed[1]; // 222 b = (typed[0] | typed[1]) & 0xFF; // 222 ? c = parseInt(d, 16); // 546
Оно?
Не совсем понимаю что вы хотите получить в результате.btd
04.04.2015 22:27+1Да, оно! Я честно говоря не думал, о таком использовании typed arrays. Спасибо хорошая идея.
Eternalko
04.04.2015 22:44-2На здоровье (:
По опыту добавлю небольшой TL;DR.
— Читайте доки начиная с MDN. Там ИМО лучше всего.
— ArrayBuffer — просто определяет кусок памяти в байтах
— TypedArray (Uint8Array/Uint16Array/...) — просто предоставляет доступ к этим байтам в каком-то формате. Мы как бы говорим JS как их читать. Cast view, так сказать.
— DataView — мне не понравился чем-то. Вроде как новый стандарт, который не взлетел.
Вот как можно использовать. Внимание, СoffeScript (не люблю скобочки и ";")
# Создаем рандомный binary. module.exports.getRandomBuffer = (mb = 1) -> buffer = new ArrayBuffer(mb * 1024 * 1024 ) i8 = new Int32Array(buffer) i = 0 while i < i8.length i8[i] = Math.random() * 100 | 0 i++ return buffer # Считаем тупой но быстрый хеш: module.exports.noobHash = (arg) -> i8 = new Int32Array(arg) hash = 0 i = 0 while i < i8.length hash += i8[i] i++ return hash
UnknownHero
03.04.2015 22:35+2Теперь ждём async/await.
Хотя и с промисами хорошо идёт.Eternalko
04.04.2015 17:53А зачем вам async/await? Просто самому приходится постоянно иметь делать с асинхронностью и я не понимаю проблемы/потребности.
a553
04.04.2015 22:44Eternalko
04.04.2015 22:57-1Это не совсем ответ. Вот быстрый рефактор.
fs.readdir source, (err, files) -> if err then console.log 'Error finding files: ' + err; return files.forEach (filename, fileIndex) -> console.log filename gm(source + filename).size (err, values) -> if err then console.log 'Error identifying file size: ' + err; return console.log filename + ' : ' + values aspect = values.width / values.height widths.forEach (width, widthIndex) => height = Math.round(width / aspect) console.log 'resizing ' + filename + 'to ' + height + 'x' + height @resize(width, height).write destination + 'w' + width + '_' + filename, (err) -> if err then console.log 'Error writing file: ' + err
А вообще тут вполне можно разделить вещи на отдельные функции и все.
async/await тут не помогутa553
04.04.2015 23:04+3А теперь нормальный, читаемый код:
try { await fs.readdir(source, defer files); await files.forEach(defer filename, defer fileIndex); console.log(filename) await gm(source + filename).size(defer values); console.log(filename + ' : ' + values) aspect = (values.width / values.height) await widths.forEach(defer width, defer widthIndex); height = Math.round(width / aspect) console.log('resizing ' + filename + 'to ' + height + 'x' + height) await this.resize(width, height).write(destination + 'w' + width + '_' + filename, defer _); } catch (e) { console.log(e); }
Eternalko
04.04.2015 23:22Теперь понятней. Спасибо.
Лично для меня он менее читаем, но это скорее всего привычка.
Действительно, у такого подхода, во многих ситуациях есть потенциал.
Вот еще равнозначный код:
sourcetry fs.readdir source, (files) -> files.forEach (filename, fileIndex) -> console.log filename gm(source + filename).size (values) -> console.log filename + ' : ' + values aspect = values.width / values.height widths.forEach (width, widthIndex) => height = Math.round(width / aspect) console.log 'resizing ' + filename + 'to ' + height + 'x' + height @resize(width, height).write destination + 'w' + width + '_' + filename catch (e) console.log e
a553
04.04.2015 23:25+1Это ошибочный код. Исключения у вас не ловятся.
Более красивая и каноничная версия async/await есть в ES7, но она совместима только с Promise.Eternalko
11.04.2015 00:58С опозданием благодарю за разъяснения и наводку на такой подход.
Нашел кучу библиотек которые таким занимаются. Пока немного сыровато, но в в общем у такого подхода есть много положительных нюансов.
symbix
05.04.2015 18:42Вы читерите немного. Перепишите на чистом JS (function function function function!, хотя тут в TS тоже есть сахарок со стрелочкой, хоть и не равнозначный), и добавьте полноценную обработку исключений из колбэков — тогда сравнение будет равноценным.
Promise/deferred проблему решают, но с await все же намного короче и читаемее.
Кофескрипт же справедливее будет сравнивать с IcedCoffee.Eternalko
11.04.2015 01:02В ES6 уже тоже есть стрелочки, так что не совсем чит. Все коллеги что из JS уже пишут в ES6 стрелочками и ок.
Тут только скобочек нет, всего навсего.
Await & ICS хорошие. ICS действительно делает много финтов ушами, особенно там, где это связано с циклами.
Приятно. Однако в работе я бы пока этого не использовал.
symbix
04.04.2015 05:34Я правильно понимаю, что с реализацией ES6 modules можно забыть про ад с ///<reference>? Если так — это просто супер.
Voronar
06.04.2015 00:33Я правильно понимаю, что ES6-модули можно будет компилировать как в виде внутренних модулей а-ля "///reference" (тупо последовательное слияние файлов), так и в виде внешних(RequireJS, CommonJS, pure ES6)?
symbix
06.04.2015 15:08Похоже, так.
TypeScript supports down-level compilation of external modules using the new ES6 syntax.
When compiling with -t ES3 or -t ES5 a module format must be chosen using -m CommonJS or -m AMD.
When compiling with -t ES6 the module format is implicitly assumed to be ECMAScript 6 and the compiler simply emits the original code with type annotations removed.
(https://github.com/Microsoft/TypeScript/issues/2242)
Насчет последовательного слияния не очень понятно, но не очень-то и надо, для этого есть gulp (или grunt, если кому нравится больше).
k12th
Итераторов и генераторов пока нету?
kichik Автор
В работе. github.com/Microsoft/TypeScript/issues/1900
k12th
Спасибо.