Нет, типы TypeScript не существуют во время выполнения

Источник: «No, TypeScript Types Don't Exist At Runtime»
Почему типы в TypeScript не существуют во время выполнения. Как TypeScript компилируется в JavaScript и чем он отличается от других языков с сильной типизацией.

Я часто участвую в дискуссиях о TypeScript в Интернете. И одно из самых распространённых заблуждений, которое встречается у людей, только что узнавших о TypeScript, заключается в том, что типы TypeScript существуют во время выполнения.

Идея кажется очевидной, когда вы приходите в TypeScript из других сильно типизированных языков. В этих языках типы являются фундаментальной частью языка. Они используются для влияния на поведение программы во время выполнения.

Но TypeScript отличается тем, что типы TypeScript не существуют во время выполнения. Они используются только для того, чтобы помочь отловить ошибки во время компиляции. Это происходит потому, что TypeScript предназначен для компиляции в JavaScript, в котором нет системы типов.

Рассмотрим несколько примеров:

Типы

Типы и интерфейсы позволяют описать форму типа. В программе будут тысячи строк с объявлениями типов. Но они не существуют во время выполнения программы:

type Person = {
name: string;
age: number;
};

const person: Person = {
name: "Alice",
age: 30,
};

interface Animal {
name: string;
age: number;
}

const animal: Animal = {
name: "Fluffy",
age: 5,
};

"use strict";
const person = {
name: "Alice",
age: 30,
};
const animal = {
name: "Fluffy",
age: 5,
};

Обратите внимание, что в транспилированном JavaScript исчезли типы Person и Animal, и всё, что осталось, — это литералы объектов.

Утверждения типов

Вы можете использовать утверждения типов, чтобы сообщить TypeScript, что вы знаете о значении больше. Но эти утверждения не существуют во время выполнения:

const str = "Hello, world!";

const num: number = str as unknown as number;

"use strict";
const str = "Hello, world!";
const num = str;

То, что num утверждается как число, не означает, что оно таковым является во время выполнения. TypeScript будет верить вам, что str — это число, но если это не так, вы получите ошибку во время выполнения.

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

Параметры функции

Типы можно использовать для описания формы параметров функции. Но эти типы не существуют во время выполнения. Они не гарантируют, что функция будет вызвана с правильными аргументами:

const add = (a: number, b: number) => a + b;

add(1, 2);

add("1" as any, "2" as any);

"use strict";
const add = (a, b) => a + b;
add(1, 2);
add("1", "2");

Обратите внимание, что в транспилированном JavaScript нет дополнительного кода для проверки того, что add вызывается с правильными аргументами.

Перечисления, пространства имён и свойства параметров

Из этого правила есть некоторые исключения. Перечисления, пространства имён и свойства параметров имеют представление во время выполнения:

// Перечисления / Enums
enum Direction {
Up,
Down,
Left,
Right,
}

// Пространства имён / Namespaces
namespace Geometry {
export const PI = 3.14159;
}

// Свойства параметров / Parameter Properties
class Person {
constructor(public name: string) {}
}

"use strict";
// Перечисления / Enums
var Direction;
(function (Direction) {
Direction[Direction["Up"] = 0] = "Up";
Direction[Direction["Down"] = 1] = "Down";
Direction[Direction["Left"] = 2] = "Left";
Direction[Direction["Right"] = 3] = "Right";
})(Direction || (Direction = {}));
// Пространства имён / Namespaces
var Geometry;
(function (Geometry) {
Geometry.PI = 3.14159;
})(Geometry || (Geometry = {}));
// Свойства параметров / Parameter Properties
class Person {
name;
constructor(name) {
this.name = name;
}
}

Большинство возможностей TypeScript исчезают во время выполнения, но эти три — исключение. Они имеют представление во время выполнения, которое можно использовать в программе.

Все эти возможности довольно старые. Они были добавлены в эпоху, когда JavaScript считался относительно застойным, а TypeScript был привлекателен тем, что добавлял такие необходимые функции, как перечисления, классы и пространства имён.

Но сейчас JavaScript находится в гораздо более здоровом состоянии. В него встроены классы. В нем есть модули, являющиеся улучшенной версией пространств имён. Когда-нибудь, согласно этому предложению, в нем появятся перечисления.

Теперь TypeScript использует другой подход — он видит свою задачу в добавлении типов в JavaScript, а не в добавлении новых возможностей в язык. Если бы перечисления, пространства имён или свойства параметров были предложены сейчас, они не были бы добавлены в TypeScript.

Это значит, что рассматривать TypeScript как просто добавление типов в JavaScript — полезное правило, за исключением перечислений, пространств имён и свойств параметров.

Дополнительные материалы

Предыдущая Статья

Laravel фасады vs псевдонимы классов

Следующая Статья

Красивый перенос текста с CSS свойством text-wrap