1. В TypeScript есть утилитарный тип **`Awaited<T>`**, который используется для извлечения типа результата, который выдает промис. Это может быть полезно в ситуациях, где вам нужно работать с типом данных, который асинхронная функция или промис возвращает, не дожидаясь его выполнения.
Давайте рассмотрим подробнее ваш пример:
```tsx
type MyAwaited<T extends PromiseLike<any>> = Awaited<T>;
```
Здесь вы определяете тип **`MyAwaited`**, который использует утилитарный тип **`Awaited`** от TypeScript. Ваш тип **`MyAwaited`** предназначен для работы с объектами, которые соответствуют интерфейсу **`PromiseLike`**, то есть объектами, которые имеют метод **`then`**. Это позволяет использовать **`MyAwaited`** для обработки объектов, похожих на промисы, но не обязательно являющихся экземплярами реализации **`Promise`**.
2. **`readonly any[]`** позволяет использовать свойство **readonly с массивами, чтобы их типы были сохранены**
```tsx
type Concat<T extends readonly any[], U extends readonly any[]> = [...T, ...U]
```
3. **`Exclude<T,U>`**- дженерик, позволяющий исключать один тип из другого
```tsx
type MyExclude<T, U> = Exclude<T, U>
```
4. **`Infer` in conditional types**
Ключевое слово **`Infer`** дополняет условные типы и не может использоваться вне расширения. Это ключевое слово позволяет нам определить переменную внутри нашего ограничения, на которую можно ссылаться или возвращать.
`infer` — это ключевое слово в TypeScript, используемое внутри **условных типов** (`Conditional Types`). Оно позволяет "выводить" **`Infer`** типы из других типов, предоставляя способ извлечения информации о типах, которые вы не можете напрямую получить.
Перейдем к примеру:
```tsx
type TypeA = { id: string }
type TypeB = { id: number }
type InferType<T> = T extends { id: infer P } ? P extends string ? string : number : any
type ResultType1 = InferType<TypeA> // string
type ResultType2 = InferType<TypeB> // number
type ResultType3 = InferType<object> // any
```
Достаем через аргументы и типизируем их в кортеж,
```tsx
type MyParameters<T extends (...args: any[]) => any> = T extends (...args: infer F) => any ? F: never
```
```tsx
type ArrayTest <T> = T extends (infer U)[] ? U: string
type FnTest <T> = T extends (...args: any[]) => infer R ? R : string
type TestObj = ArrayTest<[string, number, 'asdas']>// string | number
type TestFn = FnTest<(...args: string[]) => boolean> // boolean
```
5. **Record** - это утилитный тип TypeScript, который создает объектный тип с заданными ключами и типом значений. Простыми словами: вы говорите TypeScript "создай мне объект, где все ключи будут такими-то, а все значения - такими-то".
Представьте ситуацию: у вас есть список имен котов, и для каждого кота нужно хранить информацию (возраст и породу). Вместо того чтобы писать тип вручную, вы можете использовать `Record`, чтобы TypeScript автоматически создал правильный тип объекта.
```ts
// Сначала определяем, какие ключи будут у объекта
type CatName = "miffy" | "boris" | "mordred";
// Затем определяем, какой тип данных будет храниться в значениях
interface CatInfo {
age: number;
breed: string;
}
// Record создает тип: { miffy: CatInfo, boris: CatInfo, mordred: CatInfo }
const cats: Record<CatName, CatInfo> = {
miffy: { age: 10, breed: "Persian" },
boris: { age: 5, breed: "Maine Coon" },
mordred: { age: 16, breed: "British Shorthair" },
};
// Теперь TypeScript знает, что cats.boris существует и имеет тип CatInfo
cats.boris; // { age: 5, breed: "Maine Coon" },
```
6. **Partial** - это утилитный тип TypeScript, который делает все свойства объекта необязательными. Простыми словами: вы говорите TypeScript "возьми этот тип, но сделай так, чтобы все поля можно было не указывать". Представьте ситуацию: у вас есть тип с обязательными полями, но вам нужно создать объект, где некоторые поля могут отсутствовать (например, при обновлении данных, когда меняете только часть полей). Вместо того чтобы создавать новый тип и вручную добавлять `?` к каждому полю, вы можете использовать `Partial`, чтобы TypeScript автоматически сделал все свойства опциональными.
``` ts
interface User {
name: string;
age: number;
}
const partialUser: Partial<User> = {
name: "Bob",
}; // то есть не обязательный все поля не обязательные поэтому мы можем не писать Age
```
7. **Pick<T, K>** - это утилитный тип TypeScript, который выбирает только указанные свойства из исходного типа. Простыми словами: вы говорите TypeScript "возьми этот тип, но оставь только вот эти поля, остальные убери".
Представьте ситуацию: у вас есть большой тип с множеством полей, но для конкретной задачи нужны только несколько из них. Вместо того чтобы создавать новый тип и копировать нужные поля, вы можете использовать `Pick`, чтобы TypeScript автоматически создал тип только с выбранными свойствами.
```ts
interface User {
name: string;
age: number;
email: string;
}
type UserNameEmail = Pick<User, "name" | "email">;
const user: UserNameEmail = {
name: "Charlie",
email: "
[email protected]",
};
```
8. **Omit<T, K>** - это утилитный тип TypeScript, который исключает указанные свойства из исходного типа. Простыми словами: вы говорите TypeScript "возьми этот тип, но убери из него вот эти поля, остальные оставь" Представьте ситуацию: у вас есть тип с полями, которые нужны в одном месте, но не нужны в другом (например, секретные данные, которые нельзя передавать в API). Вместо того чтобы создавать новый тип и вручную перечислять все поля кроме ненужных, вы можете использовать `Omit`, чтобы TypeScript автоматически создал тип без указанных свойств.
```ts
interface User {
name: string;
age: number;
email: string;
}
type UserWithoutEmail = Omit<User, "email">;
const user: UserWithoutEmail = {
name: "Dave",
age: 25,
};
```