Site logo

Developer Blog

Pavel Koltyshev

Задачи по TypeScript (часть 1)

Содержание

Задания взяты из TypeScript Challenges.

Pick

Реализуйте дженерик Pick<T, K>.

Конструирует тип, выбирая набор свойств K из T.

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

interface Todo {
  title: string;
  description: string;
  completed: boolean;
}

type TodoPreview = MyPick<Todo, 'title' | 'completed'>;

const todo: TodoPreview = {
  title: 'Clean room',
  completed: false,
};

Readonly

Реализуйте дженерик Readonly<T>.

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

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

interface Todo {
  title: string;
  description: string;
}

const todo: MyReadonly<Todo> = {
  title: 'Hey',
  description: 'foobar',
};

todo.title = 'Hello'; // Error: cannot reassign a readonly property
todo.description = 'barFoo'; // Error: cannot reassign a readonly property

Tuple to Object

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

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

const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const;

type result = TupleToObject<typeof tuple>; // expected { 'tesla': 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}

Тип PropertyKey это тип состоящий из string | number | symbol.

First of Array

Реализуйте дженерик First<T>, который принимает массив T и возвращает тип его первого элемента.

type First<T extends any[]> = T extends [] ? never : T[0];

type arr1 = ['a', 'b', 'c'];
type arr2 = [3, 2, 1];

type head1 = First<arr1>; // expected to be 'a'
type head2 = First<arr2>; // expected to be 3

Length of Tuple

Реализуйте дженерик Length<T>, принимающий кортеж T и возвращающий его длину.

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

type tesla = ['tesla', 'model 3', 'model X', 'model Y'];
type spaceX = ['FALCON 9', 'FALCON HEAVY', 'DRAGON', 'STARSHIP', 'HUMAN SPACEFLIGHT'];

type teslaLength = Length<tesla>; // expected 4
type spaceXLength = Length<spaceX>; // expected 5

Exclude

Реализуйте дженерик Exclude<T, U>.
Исключает из T те типы, которые назначены U.

type MyExclude<T, U> = T extends U ? never : T;

type Result = MyExclude<'a' | 'b' | 'c', 'a'>; // 'b' | 'c'

Awaited

Если у нас есть тип, который является обернутым типом, например Promise, как мы можем получить тип, который находится внутри обернутого типа?

type MyAwaited<T extends PromiseLike<any>> =
  T extends PromiseLike<infer U> ? (U extends PromiseLike<any> ? MyAwaited<U> : U) : never;

type ExampleType = Promise<string>;

type Result = MyAwaited<ExampleType>; // string

If

Реализуйте тип утилиты If<C, T, F>, который принимает условие C, истинное значение T и ложное значение F.
Ожидается, что C будет либо истинным, либо ложным, тогда как T и F могут быть любого типа.

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

type A = If<true, 'a', 'b'>; // expected to be 'a'
type B = If<false, 'a', 'b'>; // expected to be 'b'

Concat

Реализуйте функцию JavaScript Array.concat в системе типов. Тип принимает два аргумента. Выходными данными должен быть новый массив, включающий входные данные в порядке ltr.

type Tuple = readonly unknown[];
type Concat<T extends Tuple, U extends Tuple> = [...T, ...U];

type Result = Concat<[1], [2]>; // expected to be [1, 2]

Includes

Реализуйте функцию JavaScript Array.includes в системе типов. Тип принимает два аргумента. Выходные данные должны быть логическими значениями true или false.

type Tuple = readonly unknown[];
type Includes<T extends Tuple, U> = { [k in T[number]]: true }[U] extends true ? true : false;

type isPillarMen = Includes<['Kars', 'Esidisi', 'Wamuu', 'Santana'], 'Dio'>; // expected to be `false`

Push

Реализуйте функцию JavaScript Array.push.

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

type Result = Push<[1, 2], '3'>; // [1, 2, '3']

Unshift

Реализуйте функцию JavaScript Array.unshift.

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

type Result = Unshift<[1, 2], 0>; // [0, 1, 2,]

Parameters

Реализуйте дженерик Parameters<T>.

type MyParameters<T extends (...args: any[]) => any> = T extends (...args: infer U) => any ? U : never;

type FunctionParamsType = MyParameters<typeof foo>; // [arg1: string, arg2: number]