🤓Дизайн современного TypeScript стремиться в направление "всего лишь типы".
Это означает, что ЯП почти не вводит собственных Runtime конструкций. Все что нужно, чтобы преобразовать TypeScript в JavaScript - это просто удалить типовые декларации и аннотации. И это используется такими инструментами, как ESBuild или SWC, чтобы добиться более быстрой сборки кода.
Однако, я сказал "почти". Дело в том, что в TS все таки есть такие конструкции, которые нельзя преобразовать в JS простым удалением кода. Давайте приведем примеры.
1. Поля класса через аргументы конструктора.
И аналог на JS.
2. Декораторы - уже нет. Начиная с TS5 декораторы в TS соответствует тому, как они описываются в стандарте JS. Да, спека декораторов еще не вошла в стандарт, но она находится на пред-финальной стадии полировки, так что скоро можем ожидать и нативную поддержку.
3. Пространства имен.
И аналог на JS (обычный паттерн модуль):
4. Enum. Особый вид словаря. Также является типом-суммой.
И аналог на JS:
Обратите внимание, что последний Enum транслируется 1 в 1 как простой объект JS. А в остальных случаях, у нас получается словарь, где есть отображение как для значений, так и для ключей, что бывает весьма удобно. Плюс, если мы явно не указываем значение в enum, то оно генерируется как целое не отрицательное число. Получается, что enum это такой типизированный словарь возможных значений типа. Удобно, но настолько ли, что оно стоило добавления в Runtime? В добавок тут есть и ложка дегтя: к enum не применим spread (...) оператор и нет аналога extends. Т.е. наследование перечислений на чистом ТС невозможно. Чтобы объехать, придется писать хэлперы.
5. Const Enum. Самый интересный вид Enum. Давайте рассмотрим на примере:
И аналог на JS:
Ого! В Runtime const enum вообще не представляется, т.е. это исключительно design time структура.
В остальном ТС такой же JS с точки зрения runtime. И вот тут возникает проблема: дело в том, что из-за этих 4-х пунктов (декораторы я вычеркнул) полностью корректное преобразование TS в JS сильно усложняется. Поэтому мы и видим на сайте многих инструментов, по типу SWC, что: "часть фишек ТС мы не поддерживаем". И это проблема. Ведь даже если вы их не используете, то их могут использовать другие.
И стоило оно того? Ну сахар, но не такой уж и значимый. Может нужно пометить его как deprecated и потом удалить? Предлагаю вам поварить эту мысль в голове. А я пока кину затравку на следующую статью: я расскажу вам как с помощью Enum можно радикально ускорить ваш код и уменьшить потребление памяти. В моем случае ускорение было 4-х кратным!
Хаки? Магия? Продолжение следует...
Это означает, что ЯП почти не вводит собственных Runtime конструкций. Все что нужно, чтобы преобразовать TypeScript в JavaScript - это просто удалить типовые декларации и аннотации. И это используется такими инструментами, как ESBuild или SWC, чтобы добиться более быстрой сборки кода.
Однако, я сказал "почти". Дело в том, что в TS все таки есть такие конструкции, которые нельзя преобразовать в JS простым удалением кода. Давайте приведем примеры.
1. Поля класса через аргументы конструктора.
class User {
constructor(public name: string, private age: number) {}
}
И аналог на JS.
class User {
#age;
constructor(name, age) {
this.name = name;
this.#age = age;
}
}
2. Декораторы - уже нет. Начиная с TS5 декораторы в TS соответствует тому, как они описываются в стандарте JS. Да, спека декораторов еще не вошла в стандарт, но она находится на пред-финальной стадии полировки, так что скоро можем ожидать и нативную поддержку.
3. Пространства имен.
namespace MyNamespace {
export function myFunction() {
console.log("Hello, world!");
}
}
И аналог на JS (обычный паттерн модуль):
var MyNamespace;
(function (MyNamespace) {
function myFunction() {
console.log("Hello, world!");
}
MyNamespace.myFunction = myFunction;
})(MyNamespace || (MyNamespace = {}));
4. Enum. Особый вид словаря. Также является типом-суммой.
enum PromiseState {
pending,
fulfilled,
rejected
}
enum HTTPStatuses {
ok = 200,
notFound = 404
}
enum Users {
bob = 'Bob Hilton',
ben = 'Ben Tompson'
}
И аналог на JS:
const PromiseState = {
pending: 0,
0: 'pending',
fulfilled: 1,
1: 'fulfilled',
rejected: 2,
2: 'rejected'
};
const HTTPStatuses = {
ok: 200,
200: 'ok',
notFound: 404,
404: 'notFound'
};
const Users = {
bob: 'Bob Hilton',
ben: 'Ben Tompson'
};
Обратите внимание, что последний Enum транслируется 1 в 1 как простой объект JS. А в остальных случаях, у нас получается словарь, где есть отображение как для значений, так и для ключей, что бывает весьма удобно. Плюс, если мы явно не указываем значение в enum, то оно генерируется как целое не отрицательное число. Получается, что enum это такой типизированный словарь возможных значений типа. Удобно, но настолько ли, что оно стоило добавления в Runtime? В добавок тут есть и ложка дегтя: к enum не применим spread (...) оператор и нет аналога extends. Т.е. наследование перечислений на чистом ТС невозможно. Чтобы объехать, придется писать хэлперы.
5. Const Enum. Самый интересный вид Enum. Давайте рассмотрим на примере:
const enum HTTPStatuses {
ok = 200,
notFound = 404
}
console.log(HTTPStatuses.ok);
И аналог на JS:
console.log(200);
Ого! В Runtime const enum вообще не представляется, т.е. это исключительно design time структура.
В остальном ТС такой же JS с точки зрения runtime. И вот тут возникает проблема: дело в том, что из-за этих 4-х пунктов (декораторы я вычеркнул) полностью корректное преобразование TS в JS сильно усложняется. Поэтому мы и видим на сайте многих инструментов, по типу SWC, что: "часть фишек ТС мы не поддерживаем". И это проблема. Ведь даже если вы их не используете, то их могут использовать другие.
И стоило оно того? Ну сахар, но не такой уж и значимый. Может нужно пометить его как deprecated и потом удалить? Предлагаю вам поварить эту мысль в голове. А я пока кину затравку на следующую статью: я расскажу вам как с помощью Enum можно радикально ускорить ваш код и уменьшить потребление памяти. В моем случае ускорение было 4-х кратным!
Хаки? Магия? Продолжение следует...