5 minute read

Day 40

0. TypeScript 소개

  • type이 적용된 JavaScript이다.
  • MS에서 만들었다.
  • typescript는 type을 잘 정의할 수록 좋다.

장점

  • 타입이 있다.
  • 안정성 - 컴파일 단계에서 미리 오류를 감지할 수 있다.
  • 가독성 - 타입을 보고 무엇을 하는지 미리 알 수 있다.

단점

  • 초기 설정을 해야한다.
  • 스크립트 언어의 유연성이 낮아진다.
  • 컴파일 시간이 길어질 수 있다.

1. 타입 주석과 타입 추론

  • 타입 주석은 변수, 상수 혹은 반환 값이 무슨 타입인지를 나타내는 것을 의미
  • 타입 추론은 해당 변수가 어떤 타입인지 추론하는 것. 생략하면 컴파일 타임에 알아낸다.

2. TypeScript 기본 문법

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
let a: number = 1; // 타입 주석
let b = 2; // 타입 추론
b = 'a'; // 오류 발생!
let c: boolean = false;
let d: string = 'TypeScript';
let f = {a: 1};
f.a = 2; // 가능, 이미 선언된 속성값은 마음대로 바꿀 수 있다.
f.b = 3; // 불가능, 선언되지 않은 속성값은 추가하는 것은 불가능하다.
let h: number[] = []; // 배열
h.push(1); // 가능
h.push(''); // 불가능
let i: 'good' = 'good'; // 특정 값을 type으로 지정할 수 있다.
let j: 1000 = 1000; // j 변수엔 숫자 1000만 들어갈 수 있다.
let k: any = 3; // 어떠한 값이든 가능하다. 남발하는 것은 좋진 않다.
g = '1'; // 가능
g = 3; // 가능
g = false; // 가능

// 함수의 인자, return type도 사전정의가 가능하다.
function add(a: number, b: number): number {
  return a + b;
}

console.log(add(1, 3)); // 가능
console.log(add(1, '3')); // 불가능

3. 인터페이스

  • 객체의 타입을 정의하는 방법이다.
  • 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
// 정의
interface Company {
  name: string;
  age: number;
  address?: string; // <- ?가 붙으면 Optional, undefined가 들어갈 수 있음
}

// 사용
const cobalt: Company = {
  name: 'Cobalt, Inc.',
  age: 3,
  address: 'Seoul'
}

console.log(cobalt)

// 익명 인터페이스, 코드 내에 딱 한 번만 사용할 경우 사용
const person: {
  name: string,
  age?: number
} = {
  name: 'Lee Sum-Hyoup',
  age: 100
}

4. Tuple

1
const tuple: [string, number] = ['', 0]

5. Enum

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
enum Color {
    RED, // 0
    GREEN, // 1
    BLUE // 02
}

const blue = Color.BLUE;
if (color === Color.BLUE) {

}

// 숫자가 아닌 다른 값을 할당 가능
enum Color {
    RED = 'red',
    GREEN = 'green',
    BLUE = 'blue'
}

6. 대수 타입

  • 여러 자료형의 값을 가질 수 있게 하는 방법
  • 합집합 타입과 교집합 타입이 있다.
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
35
// 합집합 타입
let numOrStr: number | string = 1;
numOrStr = 3 // 가능
numOrStr = 'str' // 가능

// 교집합 타입

let numAndStr: number & string = ''; // 원시 타입에서 사용할 수는 없다.

interface Name {
    name: string
}

interface Age {
    age: string;
}

// 값을 둘 다 넣어줘야 변수 사용 가능
let sunhyoup1: Name & Age = {
    name: 'Lee Sun-Hyoup',
    age: 100
}

// 값을 둘 중 하나만 넣어줘도 변수 사용 가능, 둘 중 하나는 들어가야 함.
let sunhyoup2: Name | Age = {
    name: 'Lee Sun-Hyoup',
    age: 100
}

// type 키워드로 새로운 타입을 정의 가능하다. 대수 타입을 type 키워드를 이용하여 새로운 타입을 정의할 수 있다.
type Person = Name & Age;
let julia: Person = {
    name: 'julia',
    age: 100
}

7. Optional

  • ES 2021에도 추가된 기능이다. 타입스크립트에는 이미 존재하였다.
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
interface Post {
    title: string;
    content: string;
}

interface ResponseData {
    post?: Post;
    message?: string;
    status: number;
}

const response: ResponseData[] = [
    {
        post: {
            title: 'Hello',
            content: 'How are you',
        },
        status: 200
    },
    {
        message: 'Error!',
        status: 500
    }
]

console.log(response[0].post.title); // Hello
console.log(response[1].post.title); // Error 발생
console.log(response[1].post?.title); // 값이 있다면 값을 반환하고 값이 없다면 자동으로 undefined를 반환한다.
console.log(response[1].post!.title); // 값이 무조건 있다는 것을 가정한다.

8. Generic

  • 하나의 인터페이스로 여러 타입을 이용할 수 있게 하는 방법
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
interface Value<T> {
    value: T;
}

const value1: Value<number> = {
    value: 1
}

const value2: Value<string> = {
    value: '1'
}

function toString<T>(a: T): string {
    return `${a}`
}

console.log(toString<number>(5)) // 5
console.log(toString<string>('5')) // 5
console.log(toString('5')) // 타입 추론이 가능해서 생략할 수 있다.

9. interface의 재활용 키워드(Partial, Required, Pick, Omit)

  • 기존 정의한 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
35
36
37
38
39
40
41
42
43
interface User {
    id: number;
    name: string;
    age: number;
    address: string;
    createdAt?: string;
    updatedAt?: string;
}

// 모든 필드가 Optional이 된다. 
const partial: Partial<User> = {} // 아무것도 안넣어줘도 사용 가능

// 모든 필드가 Required가 된다.
const required: Required<User> = {
    id: 1,
    name: 'Lee',
    age: 0,
    address: 'Seoul',
    createdAt: '',
    updatedAt: ''
}

// 특정 필드만 골라서 사용할 수 있다. 해당 필드는 반드시 포함해야 한다.
const pick: Pick<User, 'name' | 'age' | 'address'> = {
    name: '',
    age: 3,
    address: ''
}

// 특정 필드만 빼고 사용할 수 있다. 해당 필드는 사용할 수 없다.
const omit: Omit<User, 'id' | 'createdAt' | 'updatedAt'> = {
    name: '',
    age: 0,
    address: ''
}

// 시스템 속성들은 빼고 이름은 required, age와 address는 optional로 하여 User interface를 재활용한다.
const mixed: Omit<User, 'id' | 'addres' | 'age' | 'createdAt' | 'updatedAt'> & Pick<Partial<User>, 'address' | 'age'> = {
    name: '', // Required
    age: 0, // Optional
    address: '' // Optional
}

10. interface 확장 키워드(extends)

  • 특정 인터페이스를 상속받아 인터페이스를 확장할 수 있다.
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
interface Time {
    hour: number;
    minute: number;
    second: number;
}

interface DateTime extends Time {
    year: number;
    month: number;
    day: number;
}

interface OffsetDateTime extends DateTime {
    offset: number;
}

interface ZonedDateTime extends DateTime {
    zondId: string;
}

interface TimeFormat extends Pick<Time, 'hour' | 'minute'> {
    ampm: 'am' | 'pm'
}

const timeFormat: TimeFormat = {
    hour: 10,
    minute: 30,
    ampm: 'am'
}

11. 선택과제

  • 위 내용을 참고하여 그동안 만들었던 컴포넌트와 커스텀 훅을 TypeScript로 다시 작성해보세요.

TypeScript를 이용한 Todo App 재제작

필요 plugins

1
2
3
4
5
6
7
npm i -D @emotion/styled
npm i -D @storybook/react
npm i -D @types/axios
npm i -D @types/uuid
npm i -D react-router-dom

# or use `yarn add` instead of `npm i`

Categories:

Updated: