React Junior
207 subscribers
37 photos
462 links
Изучение React с нуля
加入频道
Forwarded from TypeScript Challenge
Type Challenges #11. Tuple to object

Ссылка на задачу

Условие

Нужно превратить массив в объект, ключами в котором являются элементы исходного массива.

Решение


type TupleToObject<T extends ReadonlyArray<string | number | symbol>> = {
[P in T[number]]: P
}


Прежде всего, уточняем, что ключами объекта могут быть только строки/числа/символы. Вместо перечисления можно использовать встроенный тип PropertyKey:


type TupleToObject<T extends readonly PropertyKey[]> = {
[P in T[number]]: P
}


Для получения набора элементов массива используем конструкцию T[number].

#easy
👍6
Forwarded from TypeScript Challenge
Type Challenges #189. Awaited

Ссылка на задачу

Условие

Предположим, что у нас есть тип, завернутый в другой тип, например, Promise<string>. Нужно написать утилиту MyAwaited для получения внутреннего типа.

Решение

Чтобы решить задачку, нужно понять, какая именно обертка может быть. Посмотрим на тестовые кейсы:


type X = Promise<string>
type Y = Promise<{ field: number }>
type Z = Promise<Promise<string | number>>
type Z1 = Promise<Promise<Promise<string | boolean>>>
type T = { then: (onfulfilled: (arg: number) => any) => any }

type cases = [
Expect<Equal<MyAwaited<X>, string>>,
Expect<Equal<MyAwaited<Y>, { field: number }>>,
Expect<Equal<MyAwaited<Z>, string | number>>,
Expect<Equal<MyAwaited<Z1>, string | boolean>>,
Expect<Equal<MyAwaited<T>, number>>,
]


Тут обычные промисы, а также кастомная структура с полем then. Кроме того, внутри промиса может быть другой промис и так далее.

Для описания обертки нам подойдет встроенная утилита PromiseLike<T>, осталось только вывести вложенный тип с помощью infer:


type MyAwaited<T> = T extends PromiseLike<infer A> ? A : never;


Но не забываем, что внутри обертки может быть еще одна обертка, поэтому нужно добавить немножко рекурсии:


type MyAwaited<T> = T extends PromiseLike<infer A> ? (A extends PromiseLike<infer B> ? MyAwaited<A> : A) : never;

#easy
👍2
Forwarded from TypeScript Challenge
Type Challenges. Уровень easy. Резюме

Итак, мы прорешали 13 задачек уровня easy.

4 - Pick
7 - Readonly
11 - Tuple to Object
14 - First of Array
18 - Length of Tuple
43 - Exclude
189 - Awaited
268 - If
533 - Concat
898 - Includes
3057 - Push
3060 - Unshift
3312 - Parameters

Проведем небольшую ретроспективу и отметим основные моменты решений.

🟢 1. extends

Самое популярное ключевое слово в решениях.

Используется для уточнения типов в дженериках (9 задач):


type MyPick<T, K extends keyof T>


Используется для сравнения в условных типах (2 задачи):


type If<C extends boolean, T, F> = C extends true ? T : F


Используется в комбинации с ключевым словом infer для выведения одних типов из других (4 задачи):


type First<T extends any[]> = T extends [infer F, ...any[]] ? F : never


🟢 2. Копирование ключей объекта (3 задачи)

Используется для создания Mapped Types, когда новый тип повторяет ключи исходного


type MyReadonly<T> = {
readonly [K in keyof T]: T[K]
}


🟢 3. keyof

Ключевое слово для получения набора из всех ключей объекта (2 задачи)


type MyPick<T, K extends keyof T> = {
[P in K]: T[P]
}


🟢 4. Превращение массива типов в перечисление типов(1 задача)

Используем конструкцию T[number].


type TupleToObject<T extends ReadonlyArray<string | number | symbol>> = {
[P in T[number]]: P
}


🟢 5. Использование readonly структур для работы с кортежами (3 задачи)


type Length<T extends readonly any[]> = T['length']


🟢 6. Деструктуризация массивов (5 задач)


type Push<T extends any[], U> = [...T, U]


#easy
👍4