add typescript
This commit is contained in:
60
docs/typescript/01-intro.md
Normal file
60
docs/typescript/01-intro.md
Normal file
@@ -0,0 +1,60 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Зачем нужен TS
|
||||
|
||||
TypeScript — это язык программирования, который расширяет JavaScript, добавляя статическую типизацию и другие возможности.
|
||||
|
||||
Вот основные причины, зачем он нужен:
|
||||
|
||||
1. **Статическая типизация:**
|
||||
- TypeScript позволяет определять типы переменных, параметров функций и возвращаемых значений. Это помогает находить ошибки на этапе разработки, а не во время выполнения кода.
|
||||
- Например, если вы случайно передадите строку вместо числа, TypeScript выдаст ошибку.
|
||||
|
||||
2. **Улучшение читаемости и поддержки кода:**
|
||||
- Типы делают код более понятным и самодокументируемым. Легче понять, какие данные ожидаются и возвращаются в функциях.
|
||||
- Это особенно полезно в больших проектах или при работе в команде.
|
||||
|
||||
3. **Инструменты разработки:**
|
||||
- TypeScript интегрируется с современными IDE (например, Visual Studio Code), предоставляя автодополнение, навигацию по коду и подсказки на основе типов.
|
||||
- Это ускоряет разработку и уменьшает количество ошибок.
|
||||
|
||||
4. **Совместимость с JavaScript:**
|
||||
- TypeScript — это надмножество JavaScript, поэтому любой валидный JS-код является валидным TypeScript-кодом.
|
||||
- Вы можете постепенно внедрять TypeScript в существующие проекты.
|
||||
|
||||
5. **Поддержка современных возможностей:**
|
||||
- TypeScript поддерживает современные функции ES6+ (например, классы, модули, стрелочные функции), даже если целевая среда выполнения (например, старые браузеры) их не поддерживает. TypeScript компилирует их в совместимый код.
|
||||
|
||||
6. **Повышение надежности:**
|
||||
- Статическая типизация и проверка типов снижают вероятность ошибок, связанных с неправильным использованием данных.
|
||||
- Это особенно важно в больших и сложных приложениях.
|
||||
|
||||
7. **Поддержка ООП:**
|
||||
- TypeScript предоставляет более мощные инструменты для объектно-ориентированного программирования, такие как интерфейсы, абстрактные классы, модификаторы доступа (`public`, `private`, `protected`).
|
||||
|
||||
8. **Экосистема и сообщество:**
|
||||
- TypeScript активно развивается и поддерживается Microsoft. Он широко используется в индустрии, особенно в крупных проектах (например, Angular, React, Node.js).
|
||||
|
||||
TypeScript помогает писать более надежный, читаемый и поддерживаемый код, особенно в больших проектах. Он сочетает гибкость JavaScript с преимуществами статической типизации.
|
||||
|
||||
TypeScript также включает в себя транспилятор, который преобразует TypeScript-код в JavaScript.
|
||||
|
||||
Как работает TypeScript:
|
||||
|
||||
1. **Проверка типов:**
|
||||
- TypeScript сначала проверяет типы в коде. Если есть ошибки (например, передача строки вместо числа), компилятор выдаст ошибку.
|
||||
2. **Транспиляция:**
|
||||
- После проверки типов TypeScript преобразует TypeScript-код в JavaScript. При этом он удаляет все типы и аннотации, так как они не нужны в рантайме.
|
||||
3. **Генерация кода:**
|
||||
- TypeScript генерирует JavaScript-код, который может быть выполнен в любой среде, поддерживающей JavaScript.
|
||||
|
||||
### Babel и TypeScript вместе
|
||||
Babel и TypeScript могут использоваться вместе. Например:
|
||||
|
||||
1. **TypeScript для проверки типов:**
|
||||
- TypeScript используется только для проверки типов, а транспиляцию выполняет Babel.
|
||||
- Это позволяет использовать все возможности Babel (например, экспериментальные функции JavaScript).
|
||||
2. **Babel для транспиляции:**
|
||||
- Babel может транспилировать TypeScript-код с помощью плагина `@babel/preset-typescripts`. Этот плагин удаляет типы и преобразует код в JavaScript.
|
||||
157
docs/typescript/02-types-vs-interface.md
Normal file
157
docs/typescript/02-types-vs-interface.md
Normal file
@@ -0,0 +1,157 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Отличие types от interface
|
||||
|
||||
В TypeScript и **type**, и **interface** используются для определения типов данных, но они имеют некоторые различия в синтаксисе, возможностях и использовании.
|
||||
|
||||
### 1. Синтаксис
|
||||
**`type:`**
|
||||
Используется ключевое слово type для создания псевдонимов типов.
|
||||
```ts
|
||||
type User = {
|
||||
name: string;
|
||||
age: number;
|
||||
};
|
||||
```
|
||||
**`interface:`**
|
||||
Используется ключевое слово interface.
|
||||
```ts
|
||||
interface User {
|
||||
name: string;
|
||||
age: number;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Расширение
|
||||
**`type:`**
|
||||
Для расширения типов используется оператор & (intersection).
|
||||
```ts
|
||||
type Person = {
|
||||
name: string;
|
||||
};
|
||||
|
||||
type User = Person & {
|
||||
age: number;
|
||||
};
|
||||
```
|
||||
**`interface:`**
|
||||
Для расширения интерфейсов используется ключевое слово extends.
|
||||
```ts
|
||||
interface Person {
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface User extends Person {
|
||||
age: number;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Объединение типов
|
||||
**`type:`**
|
||||
Может создавать объединения (union) и пересечения (intersection) типов.
|
||||
```ts
|
||||
type ID = string | number; // Union type
|
||||
type Combined = TypeA & TypeB; // Intersection type
|
||||
```
|
||||
**`interface:`**
|
||||
Не поддерживает объединения или пересечения напрямую. Однако можно расширять интерфейсы, чтобы достичь похожего результата.
|
||||
```ts
|
||||
interface A {
|
||||
propA: string;
|
||||
}
|
||||
|
||||
interface B {
|
||||
propB: number;
|
||||
}
|
||||
|
||||
interface Combined extends A, B {}
|
||||
```
|
||||
|
||||
### 4. Примитивные типы и сложные конструкции
|
||||
**`type:`**
|
||||
Может использоваться для определения примитивных типов, union-типов, кортежей и других сложных конструкций.
|
||||
```ts
|
||||
type StringOrNumber = string | number;
|
||||
type Tuple = [string, number];
|
||||
```
|
||||
**`interface:`**
|
||||
Используется только для описания объектов. Не может использоваться для примитивов, union-типов или кортежей.
|
||||
```ts
|
||||
// Так нельзя:
|
||||
interface StringOrNumber = string | number; // Ошибка
|
||||
```
|
||||
|
||||
### 5. Декларативное слияние
|
||||
**`type:`**
|
||||
Не поддерживает слияние. Если вы определите два типа с одинаковым именем, это вызовет ошибку.
|
||||
```ts
|
||||
type User = { name: string };
|
||||
type User = { age: number }; // Ошибка: Дубликат идентификатора 'User'
|
||||
```
|
||||
**`interface:`**
|
||||
Поддерживает слияние. Если вы определите два интерфейса с одинаковым именем, они объединятся.
|
||||
```ts
|
||||
interface User {
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface User {
|
||||
age: number;
|
||||
}
|
||||
|
||||
const user: User = {
|
||||
name: "John",
|
||||
age: 30,
|
||||
};
|
||||
```
|
||||
|
||||
### 6. Использование с классами
|
||||
**`type:`**
|
||||
Не может быть реализован классом напрямую.
|
||||
```ts
|
||||
type Person = {
|
||||
name: string;
|
||||
};
|
||||
|
||||
class User implements Person { // Ошибка: Нельзя использовать type для реализации
|
||||
name: string;
|
||||
}
|
||||
```
|
||||
**`interface:`**
|
||||
Может быть реализован классом.
|
||||
```ts
|
||||
interface Person {
|
||||
name: string;
|
||||
}
|
||||
|
||||
class User implements Person {
|
||||
name: string;
|
||||
}
|
||||
```
|
||||
|
||||
### 7. Производительность
|
||||
**`type:`**
|
||||
Может быть менее производительным при работе с большими и сложными типами, так как TypeScript каждый раз вычисляет их.
|
||||
|
||||
**`interface:`**
|
||||
Обычно работает быстрее, так как интерфейсы кэшируются и оптимизируются компилятором.
|
||||
|
||||
## Когда использовать type, а когда interface?
|
||||
|
||||
- **Используйте `type`, если:**
|
||||
- Нужно создать union-тип, intersection-тип или кортеж.
|
||||
- Работаете с примитивными типами.
|
||||
- Нужна гибкость в определении сложных типов.
|
||||
|
||||
- **Используйте `interface`, если:**
|
||||
- Работаете с объектами и классами.
|
||||
- Нужно использовать декларативное слияние.
|
||||
- Хотите, чтобы код был более читаемым и понятным для других разработчиков (интерфейсы часто ассоциируются с ООП).
|
||||
|
||||
## Итог
|
||||
- `type` и `interface` во многом похожи, но имеют свои уникальные особенности.
|
||||
- `type` более гибок и подходит для сложных типов.
|
||||
- `interface` лучше подходит для объектов и классов, а также поддерживает слияние.
|
||||
- В большинстве случаев выбор между ними зависит от предпочтений разработчика и конкретной задачи.
|
||||
222
docs/typescript/03-utility-types.md
Normal file
222
docs/typescript/03-utility-types.md
Normal file
@@ -0,0 +1,222 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Utility types
|
||||
**Utility Types** в TypeScript — это встроенные generic-типы, которые предоставляют удобные способы для преобразования или манипуляции существующими типами. Они упрощают работу с типами, позволяя создавать новые типы на основе существующих без необходимости писать сложные конструкции вручную.
|
||||
|
||||
Utility Types часто используются для создания производных типов, таких как частичные объекты, обязательные поля, исключение полей и т.д. Они особенно полезны в больших проектах, где требуется гибкость и повторное использование типов.
|
||||
|
||||
## Список популярных Utility Types
|
||||
|
||||
### 1. Partial\<T>
|
||||
Создает тип, в котором все свойства **`T`** становятся необязательными.
|
||||
|
||||
```ts
|
||||
interface User {
|
||||
name: string;
|
||||
age: number;
|
||||
}
|
||||
|
||||
type PartialUser = Partial<User>;
|
||||
// { name?: string; age?: number; }
|
||||
```
|
||||
|
||||
### 2. Required\<T>
|
||||
Создает тип, в котором все свойства **`T`** становятся обязательными.
|
||||
|
||||
```ts
|
||||
interface User {
|
||||
name?: string;
|
||||
age?: number;
|
||||
}
|
||||
|
||||
type RequiredUser = Required<User>;
|
||||
// { name: string; age: number; }
|
||||
```
|
||||
|
||||
### 3. Readonly\<T>
|
||||
Создает тип, в котором все свойства **`T`** доступны только для чтения.
|
||||
```ts
|
||||
interface User {
|
||||
name: string;
|
||||
age: number;
|
||||
}
|
||||
|
||||
type ReadonlyUser = Readonly<User>;
|
||||
// { readonly name: string; readonly age: number; }
|
||||
```
|
||||
|
||||
### 4. Record\<K, T>
|
||||
Создает тип, представляющий объект, где ключи имеют тип **`K`**, а значения — тип **`T`**.
|
||||
```ts
|
||||
type UserRoles = Record<string, string>;
|
||||
// { [key: string]: string }
|
||||
|
||||
const roles: UserRoles = {
|
||||
admin: "Admin",
|
||||
user: "User",
|
||||
};
|
||||
```
|
||||
|
||||
### 5. Pick\<T, K>
|
||||
Создает тип, выбирая только указанные свойства **`K`** из типа **`T`**.
|
||||
```ts
|
||||
interface User {
|
||||
name: string;
|
||||
age: number;
|
||||
email: string;
|
||||
}
|
||||
|
||||
type UserNameAndAge = Pick<User, "name" | "age">;
|
||||
// { name: string; age: number; }
|
||||
```
|
||||
|
||||
### 6. Omit\<T, K>
|
||||
Создает тип, исключая указанные свойства **`K`** из типа **`T`**.
|
||||
```ts
|
||||
interface User {
|
||||
name: string;
|
||||
age: number;
|
||||
email: string;
|
||||
}
|
||||
|
||||
type UserWithoutEmail = Omit<User, "email">;
|
||||
// { name: string; age: number; }
|
||||
```
|
||||
|
||||
### 7. Exclude\<T, U>
|
||||
Исключает из типа **`T`** все типы, которые можно присвоить **`U`**.
|
||||
```ts
|
||||
type T = string | number | boolean;
|
||||
type StringOrNumber = Exclude<T, boolean>;
|
||||
// string | number
|
||||
```
|
||||
|
||||
### 8. Extract\<T, U>
|
||||
Извлекает из типа **`T`** только те типы, которые можно присвоить **`U`**.
|
||||
```ts
|
||||
type T = string | number | boolean;
|
||||
type OnlyBoolean = Extract<T, boolean>;
|
||||
// boolean
|
||||
```
|
||||
|
||||
### 9. NonNullable\<T>
|
||||
Удаляет `null` и `undefined` из типа **`T`**.
|
||||
```ts
|
||||
type T = string | number | null | undefined;
|
||||
type NonNullableT = NonNullable<T>;
|
||||
// string | number
|
||||
```
|
||||
|
||||
### 10. ReturnType\<T>
|
||||
Создает тип, представляющий тип возвращаемого значения функции **`T`**.
|
||||
```ts
|
||||
function getUser() {
|
||||
return { name: "John", age: 30 };
|
||||
}
|
||||
|
||||
type UserReturnType = ReturnType<typeof getUser>;
|
||||
// { name: string; age: number; }
|
||||
```
|
||||
|
||||
### 11. Parameters\<T>
|
||||
Создает тип, представляющий кортеж параметров функции **`T`**.
|
||||
```ts
|
||||
function add(a: number, b: number) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
type AddParams = Parameters<typeof add>;
|
||||
// [a: number, b: number]
|
||||
```
|
||||
|
||||
### 12. ConstructorParameters\<T>
|
||||
Создает тип, представляющий кортеж параметров конструктора класса **`T`**.
|
||||
```ts
|
||||
class User {
|
||||
constructor(public name: string, public age: number) {}
|
||||
}
|
||||
|
||||
type UserConstructorParams = ConstructorParameters<typeof User>;
|
||||
// [name: string, age: number]
|
||||
```
|
||||
|
||||
### 13. InstanceType\<T>
|
||||
Создает тип, представляющий тип экземпляра класса **`T`**.
|
||||
```ts
|
||||
class User {
|
||||
name: string;
|
||||
age: number;
|
||||
}
|
||||
|
||||
type UserInstance = InstanceType<typeof User>;
|
||||
// User
|
||||
```
|
||||
|
||||
### 14. ThisParameterType\<T>
|
||||
Извлекает тип параметра **`this`** из функции **`T`**.
|
||||
```ts
|
||||
function greet(this: { name: string }) {
|
||||
console.log(`Hello, ${this.name}`);
|
||||
}
|
||||
|
||||
type GreetThisType = ThisParameterType<typeof greet>;
|
||||
// { name: string }
|
||||
```
|
||||
|
||||
### 15. OmitThisParameter\<T>
|
||||
Создает тип функции, удаляя параметр **`this`**.
|
||||
```ts
|
||||
function greet(this: { name: string }) {
|
||||
console.log(`Hello, ${this.name}`);
|
||||
}
|
||||
|
||||
type GreetWithoutThis = OmitThisParameter<typeof greet>;
|
||||
// () => void
|
||||
```
|
||||
|
||||
|
||||
## Примеры использования Utility Types
|
||||
#### Пример 1: Создание частичного объекта
|
||||
```ts
|
||||
interface User {
|
||||
name: string;
|
||||
age: number;
|
||||
email: string;
|
||||
}
|
||||
|
||||
type PartialUser = Partial<User>;
|
||||
// { name?: string; age?: number; email?: string; }
|
||||
```
|
||||
#### Пример 2: Выбор конкретных свойств
|
||||
```ts
|
||||
interface User {
|
||||
name: string;
|
||||
age: number;
|
||||
email: string;
|
||||
}
|
||||
|
||||
type UserNameAndEmail = Pick<User, "name" | "email">;
|
||||
// { name: string; email: string; }
|
||||
```
|
||||
#### Пример 3: Исключение свойств
|
||||
```ts
|
||||
interface User {
|
||||
name: string;
|
||||
age: number;
|
||||
email: string;
|
||||
}
|
||||
|
||||
type UserWithoutEmail = Omit<User, "email">;
|
||||
// { name: string; age: number; }
|
||||
```
|
||||
|
||||
## Итог
|
||||
**Utility Types** в TypeScript — это мощный инструмент для работы с типами. Они позволяют:
|
||||
|
||||
- Упрощать создание новых типов на основе существующих.
|
||||
- Уменьшать дублирование кода.
|
||||
- Повышать читаемость и поддерживаемость кода.
|
||||
|
||||
Использование **Utility Types** делает TypeScript более гибким и выразительным, особенно в больших проектах.
|
||||
86
docs/typescript/04-generic-types.md
Normal file
86
docs/typescript/04-generic-types.md
Normal file
@@ -0,0 +1,86 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
# Generic types
|
||||
|
||||
**Generics (обобщения)** в TypeScript — это механизм, который позволяет создавать универсальные, переиспользуемые компоненты (функции, классы, интерфейсы), которые могут работать с разными типами данных, сохраняя при этом безопасность типов.
|
||||
|
||||
## Зачем нужны Generics?
|
||||
- **Повторное использование кода:** Generics позволяют писать универсальные функции и классы, которые могут работать с любыми типами.
|
||||
- **Безопасность типов:** Generics сохраняют информацию о типах, что помогает избежать ошибок на этапе компиляции.
|
||||
- **Гибкость:** Generics позволяют создавать компоненты, которые могут адаптироваться к разным типам данных.
|
||||
|
||||
## Примеры использования Generics
|
||||
|
||||
### 1. Функции с Generics
|
||||
```ts
|
||||
function identity<T>(arg: T): T {
|
||||
return arg;
|
||||
}
|
||||
|
||||
let output1 = identity<string>("Hello"); // Тип: string
|
||||
let output2 = identity<number>(42); // Тип: number
|
||||
```
|
||||
**`T`** — это обобщенный тип (type parameter), который заменяется на конкретный тип при вызове функции.
|
||||
|
||||
### 2. Классы с Generics
|
||||
```ts
|
||||
class Box<T> {
|
||||
private value: T;
|
||||
|
||||
constructor(value: T) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
getValue(): T {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
let box1 = new Box<string>("Hello");
|
||||
let box2 = new Box<number>(42);
|
||||
```
|
||||
Класс **`Box`** может работать с любым типом данных, переданным в **`T`**.
|
||||
|
||||
### 3. Интерфейсы с Generics
|
||||
```ts
|
||||
interface Pair<T, U> {
|
||||
first: T;
|
||||
second: U;
|
||||
}
|
||||
|
||||
let pair: Pair<string, number> = { first: "Age", second: 30 };
|
||||
```
|
||||
Интерфейс **`Pair`** может работать с двумя разными типами (**`T`** и **`U`**).
|
||||
|
||||
### 4. Ограничения Generics (Constraints)
|
||||
Иногда нужно ограничить типы, которые можно передать в Generics. Для этого используется ключевое слово **`extends`**.
|
||||
```ts
|
||||
interface Lengthwise {
|
||||
length: number;
|
||||
}
|
||||
|
||||
function logLength<T extends Lengthwise>(arg: T): void {
|
||||
console.log(arg.length);
|
||||
}
|
||||
|
||||
logLength("Hello"); // ОК, у строки есть свойство length
|
||||
logLength([1, 2, 3]); // ОК, у массива есть свойство length
|
||||
logLength(42); // Ошибка: у числа нет свойства length
|
||||
```
|
||||
|
||||
### 5. Generics по умолчанию
|
||||
Можно указать тип по умолчанию для Generics, если тип не был передан явно.
|
||||
```ts
|
||||
function createArray<T = string>(length: number, value: T): T[] {
|
||||
return Array(length).fill(value);
|
||||
}
|
||||
|
||||
let strings = createArray(3, "x"); // string[]
|
||||
let numbers = createArray<number>(3, 42); // number[]
|
||||
```
|
||||
## Преимущества Generics
|
||||
- **Универсальность:** Generics позволяют писать код, который работает с разными типами.
|
||||
- **Безопасность типов:** TypeScript проверяет типы на этапе компиляции, что помогает избежать ошибок.
|
||||
- **Читаемость:** Generics делают код более выразительным и понятным.
|
||||
113
docs/typescript/05-type-guards.md
Normal file
113
docs/typescript/05-type-guards.md
Normal file
@@ -0,0 +1,113 @@
|
||||
---
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
# Type guards
|
||||
**Type Guards (защитники типов)** в TypeScript — это механизм, который позволяет сужать тип переменной внутри блока кода на основе проверки условий. Это помогает TypeScript лучше понимать, с каким типом данных он работает, и обеспечивает безопасность типов.
|
||||
|
||||
## Зачем нужны Type Guards?
|
||||
- **Сужение типов:** TypeScript может автоматически определять тип переменной внутри блока кода после проверки.
|
||||
- **Безопасность типов:** Type Guards помогают избежать ошибок, связанных с неправильным использованием типов.
|
||||
- **Улучшение читаемости:** Код становится более понятным, так как явно указываются условия для работы с разными типами.
|
||||
|
||||
## Основные виды Type Guards
|
||||
|
||||
### 1. `typeof`
|
||||
Проверяет тип примитивных значений (string, number, boolean, symbol, undefined, object, function).
|
||||
```ts
|
||||
function printValue(value: string | number) {
|
||||
if (typeof value === "string") {
|
||||
console.log(value.toUpperCase()); // Тип value: string
|
||||
} else {
|
||||
console.log(value.toFixed(2)); // Тип value: number
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. `instanceof`
|
||||
Проверяет, является ли объект экземпляром определенного класса.
|
||||
|
||||
```ts
|
||||
class Dog {
|
||||
bark() {
|
||||
console.log("Woof!");
|
||||
}
|
||||
}
|
||||
|
||||
class Cat {
|
||||
meow() {
|
||||
console.log("Meow!");
|
||||
}
|
||||
}
|
||||
|
||||
function makeSound(animal: Dog | Cat) {
|
||||
if (animal instanceof Dog) {
|
||||
animal.bark(); // Тип animal: Dog
|
||||
} else {
|
||||
animal.meow(); // Тип animal: Cat
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Проверка на `null` или `undefined`
|
||||
Позволяет исключить `null` или `undefined` из типа.
|
||||
```ts
|
||||
function printLength(value: string | null) {
|
||||
if (value !== null) {
|
||||
console.log(value.length); // Тип value: string
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Пользовательские Type Guards
|
||||
Функции, которые возвращают **`boolean`** и помогают TypeScript сузить тип.
|
||||
```ts
|
||||
interface Bird {
|
||||
fly(): void;
|
||||
}
|
||||
|
||||
interface Fish {
|
||||
swim(): void;
|
||||
}
|
||||
|
||||
function isFish(pet: Bird | Fish): pet is Fish {
|
||||
return (pet as Fish).swim !== undefined;
|
||||
}
|
||||
|
||||
function move(pet: Bird | Fish) {
|
||||
if (isFish(pet)) {
|
||||
pet.swim(); // Тип pet: Fish
|
||||
} else {
|
||||
pet.fly(); // Тип pet: Bird
|
||||
}
|
||||
}
|
||||
```
|
||||
Обратите внимание на синтаксис **`pet is Fish`**. Это указывает TypeScript, что если функция возвращает **`true`**, то **`pet`** имеет тип **`Fish`**.
|
||||
|
||||
### 5. Проверка свойств объекта
|
||||
Позволяет сузить тип на основе наличия определенного свойства.
|
||||
```ts
|
||||
interface Car {
|
||||
drive(): void;
|
||||
}
|
||||
|
||||
interface Boat {
|
||||
sail(): void;
|
||||
}
|
||||
|
||||
function move(vehicle: Car | Boat) {
|
||||
if ("drive" in vehicle) {
|
||||
vehicle.drive(); // Тип vehicle: Car
|
||||
} else {
|
||||
vehicle.sail(); // Тип vehicle: Boat
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Итог
|
||||
**Type Guards** — это мощный инструмент TypeScript для работы с типами. Они позволяют:
|
||||
- Сужать типы на основе условий.
|
||||
- Повышать безопасность кода.
|
||||
- Делать код более читаемым и выразительным.
|
||||
|
||||
Используйте **Type Guards**, чтобы TypeScript лучше понимал ваши намерения и помогал избегать ошибок.
|
||||
97
docs/typescript/06-enums-vs-as-const.md
Normal file
97
docs/typescript/06-enums-vs-as-const.md
Normal file
@@ -0,0 +1,97 @@
|
||||
---
|
||||
sidebar_position: 6
|
||||
---
|
||||
|
||||
# Enums и as const
|
||||
**Enum (перечисления)** в TypeScript — это способ определения набора именованных констант. Enums полезны, когда нужно работать с набором связанных значений, которые имеют смысл только в контексте друг друга.
|
||||
|
||||
## Пример Enum
|
||||
```ts
|
||||
enum Direction {
|
||||
Up = "UP",
|
||||
Down = "DOWN",
|
||||
Left = "LEFT",
|
||||
Right = "RIGHT",
|
||||
}
|
||||
|
||||
let move: Direction = Direction.Up;
|
||||
console.log(move); // "UP"
|
||||
```
|
||||
|
||||
## Особенности Enum
|
||||
|
||||
### 1. Числовые Enums:
|
||||
Если значения не указаны явно, TypeScript автоматически присваивает числа, начиная с 0.
|
||||
```ts
|
||||
enum Status {
|
||||
Pending, // 0
|
||||
Approved, // 1
|
||||
Rejected, // 2
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Строковые Enums:
|
||||
Каждое значение должно быть явно указано.
|
||||
```ts
|
||||
enum Direction {
|
||||
Up = "UP",
|
||||
Down = "DOWN",
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Гетерогенные Enums:
|
||||
Можно смешивать строковые и числовые значения (но это не рекомендуется).
|
||||
```ts
|
||||
enum Mixed {
|
||||
Yes = 1,
|
||||
No = "NO",
|
||||
}
|
||||
```
|
||||
|
||||
## Проблемы с Enum
|
||||
- **Генерируют дополнительный код:** Enums компилируются в JavaScript-объекты, что может увеличить размер кода.
|
||||
- **Не всегда интуитивно понятны:** Например, числовые Enums могут быть неочевидными.
|
||||
- **Сложности с деревомизацией (tree-shaking):** Enums могут мешать оптимизации кода при сборке.
|
||||
|
||||
### Замена Enum с помощью `as const`
|
||||
В TypeScript можно использовать объекты с **`as const`**, чтобы создать тип, аналогичный **Enum**, но без его недостатков.
|
||||
|
||||
```ts
|
||||
const Direction = {
|
||||
Up: "UP",
|
||||
Down: "DOWN",
|
||||
Left: "LEFT",
|
||||
Right: "RIGHT",
|
||||
} as const;
|
||||
|
||||
type Direction = typeof Direction[keyof typeof Direction];
|
||||
|
||||
let move: Direction = Direction.Up;
|
||||
console.log(move); // "UP"
|
||||
```
|
||||
|
||||
### Преимущества `as const`:
|
||||
- **Без дополнительного кода:** **`as const`** не генерирует дополнительный код в JavaScript.
|
||||
- **Иммутабельность:** Значения становятся read-only.
|
||||
- **Деревоизация:** Легче оптимизировать при сборке.
|
||||
- **Гибкость:** Можно использовать строки, числа и другие типы.
|
||||
|
||||
### Пример с числовыми значениями:
|
||||
```ts
|
||||
const Status = {
|
||||
Pending: 0,
|
||||
Approved: 1,
|
||||
Rejected: 2,
|
||||
} as const;
|
||||
|
||||
type Status = typeof Status[keyof typeof Status];
|
||||
|
||||
let currentStatus: Status = Status.Approved;
|
||||
console.log(currentStatus); // 1
|
||||
```
|
||||
|
||||
## Итог
|
||||
- **Enum** — это классический способ определения набора констант, но он имеет недостатки.
|
||||
- **`as const`** — это современная альтернатива, которая более гибкая и эффективная.
|
||||
|
||||
Используйте **`as const`**, если хотите избежать недостатков Enum и сделать код более легковесным и оптимизированным.
|
||||
7
docs/typescript/_category_.json
Normal file
7
docs/typescript/_category_.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "Typescript",
|
||||
"position": 4,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user