Typescript utils

typescript

  • Conditional Types
  • Mapped Types
  • Utility Types

Type Alias 와 Interface 뭘 써야 할까?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
type PositionType = {
x: number;
y: number;
}
interface PositionInterface {
x: number;
y: number;
}

// object
const obj1: PositionType = {
x: 1,
y: 1,
}
const obj2: PostionInterface {
x: number;
y: number;
}

//class
class Pos1 implements PositionType {
x: number;
y: number;
}
class Pos2 implements PositionIneterface {
x: number;
y: number;
}

// Extends
interface ZPositionInterface extends PositionInterface {
z: number;
}
type ZpoistionType = PostionType & {z: number}

차이점은 Interface 만 결합이 가능하다. 정의가 2개 되어 있으면 두개가 합쳐짐.

1
2
3
4
// Only interrace can be merged.
interface PostionInterface {
z: number;
}

type 은 computed properties 를 사용 가능하다.

1
2
3
4
5
type Person = {
name: string;
age: number;
}
type Name = Person['name'] // string

개념적인 차이

Interface 란 계약서이다. 규격 사항으로 정의하고 어떤 규격 사항대로 정의하도록 사용하고 싶다면 interface 를 사용한다.

type 은 데이터의 모습을 정의한다. 단순의 데이터의 모습을 정의한다면 type 을 사용하는것이 좋다.

Utility types

type 을 변형 시키는 것이 typescript 에서는 가능하다.

IndexType

1
2
3
4
5
6
const obj = {
name: 'koo',
}

obj.name // koo
obj[name] // koo

Animal type :

1
2
3
4
5
6
7
8
9
type Animal = {
name: string;
age: number;
gender: 'male' | 'female'
}
type Name = Animal['name'] // string
type Gender = Animal['gender'] // 'male' | 'female'

type Keys = keyof Animal //'name' | 'age' | 'gender'

Pertson type :

1
2
3
4
5
6
7
8
type Person = {
name: string;
gender: Animal['gender']
}
const person: Person = {
name: 'koo',
gender: 'male'
}

MappedType

1
2
3
4
5
6
7
8
type Video = {
title string;
author: string;
}
type VideoOptional = {
title?: string;
author?: string;
}

맵 타입으로 이런 작업을 할 수 있다.

1
2
3
4
5
6
7
8
// type 정의 안에서 in 사용 가능
type Optional<T> = {
[P in keyof T]?: T[P]
}
type VideoOptional = Optional<Video>;
const videoOp: VideoOptional = {
title: 'hi'
}

readonly:

1
2
3
type ReadOnly<T> = {
readonly [P in keyof T]: T[P];
}

Proxy :

1
2
3
4
5
6
7
type Proxy<T> = {
get(): T;
set(value: T): void;
}
type Proxify<T> = {
[P in keyof T]: Proxy<T[P>;
}

Conditional type

type 에도 조건을 줄 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
type Check<T> = T extends string? boolean : number;
type Type = Check<string> // boolean

type TypeName<T> = T extends string
? 'string'
: T extends number
? 'number'
: T extends boolean
? 'boolean'
: T extends undefined
? 'undefined'
: T extends Function
? 'function'
: 'object'

ReadOnly

1
2
3
4
5
6
7
8
type ToDo = {
title: string;
description: string;
}
// 위에서 작성했지만 사실 왠만한 utility type 은 정의되어 있다.
function display(todo Readonly<ToDo>) {
...
}

PartialType

1
2
3
4
5
6
7
8
9
type Todo = {
title: string;
description: string;
label: string;
priority: 'high' | 'low'
}
function updateTodo(todo: Todo, fieldsToUpdate: Partial<ToDo>) : ToDo {
return {...todo, ...fieldsToUpdate };
}

PickType

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
type Video = {
id: string;
title: sstring;
url: string;
data: string;
}
// video 에 모든 정보를 반환함 - 무거움
function getVideo(id: string): Video {
return {
id,
title: 'video',
url: 'dfdf',
data: 'byte-data'
}
// meta 정보만 반환
function getVideoMetaData(id: string): Pick<Video, 'id' | 'title'> {
return {
id,
title: 'title'
}
}

OmitType

원하는 것만 빼는것 가능

1
type VideoMetaData = Omit<Video, 'url' | 'data'>

Record