TypeScript для программистов JavaScript
TypeScript имеет необычные отношения с JavaScript. TypeScript предоставляет все возможности JavaScript и дополнительный уровень поверх них: систему типов TypeScript.
Например, JavaScript предоставляет базовые элементы языка, такие как string и number, но не проверяет, что вы последовательно их присваиваете. TypeScript это делает.
Это означает, что ваш существующий работающий код JavaScript также является кодом TypeScript. Основное преимущество TypeScript заключается в том, что он может выявлять неожиданное поведение в вашем коде, снижая вероятность ошибок.
Этот учебник предоставляет краткий обзор TypeScript, сфокусированный на его системе типов.
Типы по умолчанию
TypeScript знает язык JavaScript и во многих случаях сгенерирует типы для вас. Например, при создании переменной и присвоении ей определённого значения, TypeScript будет использовать это значение в качестве её типа.
let helloWorld = "Hello World";
Понимая, как работает JavaScript, TypeScript может построить систему типов, которая принимает код JavaScript, но имеет типы. Это предоставляет систему типов без необходимости добавлять дополнительные символы, чтобы сделать типы явными в вашем коде. Именно так TypeScript понимает, что helloWorld является string в приведённом выше примере.
Возможно, вы писали JavaScript в Visual Studio Code и использовали автодополнение редактора. Visual Studio Code использует TypeScript под капотом, чтобы облегчить работу с JavaScript.
Определение типов
Вы можете использовать широкий спектр шаблонов проектирования в JavaScript. Однако некоторые шаблоны проектирования затрудняют автоматическое выведение типов (например, шаблоны, использующие динамическое программирование). Чтобы охватить эти случаи, TypeScript поддерживает расширение языка JavaScript, которое предоставляет места, где вы можете указать TypeScript, какими должны быть типы.
Например, чтобы создать объект с выведенным типом, включающим name: string и id: number, вы можете написать:
const user = {
name: "Hayes",
id: 0,
}; Вы можете явно описать форму этого объекта с помощью объявления interface:
interface User {
name: string;
id: number;
} Затем вы можете объявить, что объект JavaScript соответствует форме вашего нового interface, используя синтаксис, подобный : TypeName после объявления переменной:
const user: User = {
name: "Hayes",
id: 0,
}; Если вы предоставите объект, который не соответствует предоставленному интерфейсу, TypeScript предупредит вас:
interface User {
name: string;
id: number;
}
const user: User = {
username: "Hayes",
id: 0,
}; Поскольку JavaScript поддерживает классы и объектно-ориентированное программирование, то же самое делает и TypeScript. Вы можете использовать объявление интерфейса с классами:
interface User {
name: string;
id: number;
}
class UserAccount {
name: string;
id: number;
constructor(name: string, id: number) {
this.name = name;
this.id = id;
}
}
const user: User = new UserAccount("Murphy", 1); Вы можете использовать интерфейсы для аннотирования параметров и возвращаемых значений функций:
function deleteUser(user: User) {
// ...
}
function getAdminUser(): User {
//...
} В JavaScript уже доступен небольшой набор примитивных типов: boolean, bigint, null, number, string, symbol, и undefined, которые можно использовать в интерфейсе. TypeScript расширяет этот список ещё несколькими, такими как any (разрешает всё), unknown (обеспечивает, что кто-то, использующий этот тип, объявляет, чем является тип), never (невозможно, чтобы этот тип произошёл), и void (функция, которая возвращает undefined или не имеет возвращаемого значения).
Вы увидите, что для построения типов существуют два синтаксиса: Интерфейсы и Типы. Вы должны отдавать предпочтение interface. Используйте type в случае необходимости специфических функций.
Комбинирование типов
С помощью TypeScript вы можете создавать сложные типы, комбинируя простые. Существуют два распространённых способа: с объединениями и с дженериками.
Объединения
С объединением вы можете объявить, что тип может быть одним из многих типов. Например, вы можете описать тип boolean как либо true или false:
type MyBool = true | false;
Примечание: Если вы наведёте курсор на MyBool выше, вы увидите, что он классифицируется как boolean. Это свойство структурной системы типов. Подробнее об этом ниже.
Распространённый случай использования объединений типов — описание набора string или number литералов, которыми может быть значение:
type WindowStates = "open" | "closed" | "minimized"; type LockStates = "locked" | "unlocked"; type PositiveOddNumbersUnderTen = 1 | 3 | 5 | 7 | 9;
Объединения также обеспечивают способ работы с различными типами. Например, у вас может быть функция, которая принимает array или string:
function getLength(obj: string | string[]) {
return obj.length;
} Чтобы узнать тип переменной, используйте typeof:
| Тип | Предикат |
|---|---|
| строка | typeof s === "string" |
| число | typeof n === "number" |
| логическое | typeof b === "boolean" |
| undefined | typeof undefined === "undefined" |
| функция | typeof f === "function" |
| массив | Array.isArray(a) |
Например, вы можете заставить функцию возвращать разные значения в зависимости от того, передаётся ли ей строка или массив:
function wrapInArray(obj: string | string[]) {
if (typeof obj === "string") {
return [obj];
}
return obj;
} Дженерики
Дженерики предоставляют переменные для типов. Общий пример — массив. Массив без дженериков может содержать что угодно. Массив с дженериками может описать значения, которые массив содержит.
type StringArray = Array<string>;
type NumberArray = Array<number>;
type ObjectWithNameArray = Array<{ name: string }>; Вы можете объявить свои собственные типы, использующие дженерики:
interface Backpack<Type> {
add: (obj: Type) => void;
get: () => Type;
}
// This line is a shortcut to tell TypeScript there is a
// constant called `backpack`, and to not worry about where it came from.
declare const backpack: Backpack<string>;
// object is a string, because we declared it above as the variable part of Backpack.
const object = backpack.get();
// Since the backpack variable is a string, you can't pass a number to the add function.
backpack.add(23); Структурная система типов
Одним из основных принципов TypeScript является то, что проверка типов фокусируется на форме, которую имеют значения. Это иногда называется «типизацией по поведению» или «структурной типизацией».
В структурной системе типов, если два объекта имеют одинаковую форму, они считаются одного типа.
interface Point {
x: number;
y: number;
}
function logPoint(p: Point) {
console.log(`${p.x}, ${p.y}`);
}
// logs "12, 26"
const point = { x: 12, y: 26 };
logPoint(point); Переменная point никогда не объявляется как тип Point. Однако TypeScript сравнивает форму point с формой Point при проверке типов. Они имеют одинаковую форму, поэтому код проходит.
Совпадение по форме требует только подмножества полей объекта для соответствия.
const point3 = { x: 12, y: 26, z: 89 };
logPoint(point3); // logs "12, 26"
const rect = { x: 33, y: 3, width: 30, height: 80 };
logPoint(rect); // logs "33, 3"
const color = { hex: "#187ABF" };
logPoint(color); Нет никакой разницы в том, как классы и объекты соответствуют формам:
class VirtualPoint {
x: number;
y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
const newVPoint = new VirtualPoint(13, 56);
logPoint(newVPoint); // logs "13, 56" Если объект или класс имеют все необходимые свойства, TypeScript скажет, что они соответствуют, независимо от деталей реализации.
Следующие шаги
Это был краткий обзор синтаксиса и инструментов, используемых в повседневной работе с TypeScript. Отсюда вы можете:
- Прочитать полное руководство от начала до конца
- Изучить примеры на игровой площадке
© 2012-2023 Microsoft
Licensed under the Apache License, Version 2.0.
https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html