본문 바로가기
스터디

[Typescript] Type Challenge

by rious275 2023. 7. 23.

Type Challenge

챌린지 링크

타입스크립트의 여러 유형과 유틸리티들의 작동 방식을 이해하도록 돕는 도전 형태

4-Pick

내장 유틸리티 Pick<T, 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,
};

/** 풀이 */

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

7-Readonly

내장 유틸리티 Readonly<T>를 사용하지 않고 구현해보기. (T의 모든 프로퍼티가 읽기 전용으로 설정된 타입을 생성한다)

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

/** 풀이 */

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

11-Tuple to Object

주어진 배열을 key: value 형태의 객체로 변환하기. (key와 value는 동일하게 배열 요소로 구성된다)

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'}

/** 풀이 */

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

14-First of Array

주어진 배열 T의 첫 번째 요소를 반환하는 제네릭 구현하기

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

/** 풀이 */

type First<T extends (string | number)[]> = T[0];

18-Length of Tuple

주어진 튜플의 길이를 선택하기

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

/** 풀이 */

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

43-Exclude

주어진 리터럴에서 두 번째 타입을 제외하기 (Exclude<T, U> 구현)

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

/** 풀이 */

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

189-Awaited

Promise와 같이 래핑된 타입이 있는 경우. 안에 있는 타입을 구하기

type ExampleType = Promise<string>;

type Result = MyAwaited<ExampleType>; // string

/** 풀이 */

type MyAwaited<T> = T extends Promise<infer U> ? U : T;

268-If

조건 C가 참일 때 T, 거짓일 때 F를 선택하기

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

/** 풀이 */

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

533-Concat

Javascript Array.concat 구현하기 (두 개의 인수를 받아서 새로운 배열을 반환)

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

/** 풀이 */

type Concat<T extends number[], U extends number[]> = [...T, ...U];

898-Includes

Javascript Array.includes 구현하기 (두 개의 인수를 받아서 boolean 출력)

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

/** 풀이 */

type Includes<T extends string[], U> = U extends T[keyof T] ? true : false;

3507-Push

Javascript Array.push 구현하기

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

/** 풀이 */

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

3060-Unshift

Javascript Array.unshift 구현하기

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

3312-Parameters

매개변수 구현하기

const foo = (arg1: string, arg2: number): void => {};

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

/** 풀이 */

type MyParameters<T extends typeof foo> = T extends (...args: infer U) => void
  ? U
  : never;