Day40
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`