1️⃣ 타입스크립트 기본 타입
String
1
| let color: string = "blue";
|
Number
1
| let decimal: number = 6;
|
Boolean
1
| let isDone: boolean = true;
|
Array
1
2
| let list: number[] = [1, 2, 3];
let list: Array<number> = [1, 2, 3];
|
Object
1
| const user:object = { name:"민또", age:19 }
|
Tuple ➡️ 고정된 개수의 요소를 가지며 각 요소의 타입이 지정된 배열
1
| const arr: [string, number] = ['Bellingham', 22];
|
Null / Undefined
1
2
| let u: undefined = undefined;
let n: null = null;
|
Any ➡️ 어떤 타입이든 상관 X
그 외 ➡️ Enum, Never, Void
🚀 함수 타입
1️⃣ 매개변수 타입 지정
1
2
3
| function add(x: number, y: number): { return x + y };
add(10, 20); // 가능
add("x", "y") // 불가능
|
2️⃣ 반환 값 타입 지정
1
| function add(x, y):number { return x + y }; // 반환 값 반드시 Number 형
|
3️⃣ 옵셔널 파라미터
선택적 매개변수는 "?"를 사용하여 정의
1
2
3
4
5
6
7
8
9
10
| function optionalName(firstName: string, lastName?: string): string {
if(lastName) {
return firstName + " " + lastName;
} else {
return firstName;
}
}
console.log(optionalName("Minddo", "Heo")); // Minddo Heo
console.log(optionalName("Minddo")); // Minddo
|
🚀 타입 오퍼레이터
1️⃣ 유니언 타입
유니언 타입은 여러 개의 타입을 결합하여 변수에 할당할 수 있는 값을 다양하게 만들 수 있음
유니언 타입은 연결된 타입 중 1개만 만족하면 됨
1
2
3
4
| let value: string | number;
value = "minddo"; // OK
value = 19; // OK
|
- But
특정 타입의 메소드를 사용하려고 하면 에러가 발생 할 수 있음
- ☝🏻 때문에
Type Guard
사용하기
Type Guard
➡️ 런타임에 변수의 타입 확인 후, 그에 따라 해당 타입의 메소드 사용할 수 있도록 해줌
typeof
연산자 사용한 타입 가드
- 원시 타입 확인에 유용
1
2
3
4
5
6
7
8
9
| function printId(id: number | string) {
if (typeof id === "string") {
// id가 string 타입인 경우
console.log(`ID (string): ${id.toUpperCase()}`);
} else {
// id가 number 타입인 경우
console.log(`ID (number): ${id}`);
}
}
|
instanceof
연산자 사용한 타입 가드
- 객체가 특정 클래스의 인스턴스인지 확인할 때 사용
코드 보기
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
| class ManchesterUTD {
utd() {
console.log("근본");
}
}
class ManchesterCity {
city() {
console.log("노근본");
}
}
type Club = ManchesterUTD | ManchesterCity;
function favorite(club: Club) {
if (club instanceof ManchesterUTD) {
club.utd();
} else {
club.city();
}
}
let mu = new ManchesterUTD();
let mc = new ManchesterCity();
favorite(mu);
favorite(mc);
|
2️⃣ 인터섹션 타입
인터섹션 타입은 여러 타입을 결합하여 하나의 복합 타입을 만들 수 있음
인터섹션 타입은 연결된 타입을 모두 만족해야함
1
2
3
4
5
| const introduce: { name: string; age: number } & { job: string } = {
name: "Bellingham",
age: 22,
job: "Soccer Player",
};
|
🚀 인터페이스
객체의 타입을 정의할 때 사용하는 도구
1️⃣ 기본 인터페이스 정의
1
2
3
4
5
6
7
8
9
| interface Person {
name: string;
age: number;
}
let person: Person = {
name: "minddo",
age: 29
};
|
2️⃣ 인터페이스 병합
1
2
3
4
5
6
7
8
9
10
11
12
| interface Person {
name: string;
}
interface Person {
age: number;
}
const player: Person = {
name: "Bellingham",
age: 22
};
|
3️⃣ 인터페이스 상속
1
2
3
4
5
6
7
8
9
10
11
12
| interface Club {
uniformColor: string;
}
interface ManUtd extends Club {
country: string;
}
const player: Person = {
uniformColor: "Red",
country: "England"
};
|
4️⃣ 인덱스 시그니처
객체가 임의의 속성을 가질 수 있도록 정의
1
2
3
4
5
6
7
8
9
10
11
12
| interface ClubDictionary {
[key: string]: string | number;
}
let manU: ClubDictionary = {
name: "ManchesterUtd",
rank: 1,
country: "England",
stadium: "Old Trafford"
};
console.log(manU);
|
🐥 변수에 인터페이스 적용
1
2
3
4
5
6
7
8
9
| interface User {
username: string;
password: string;
}
const user: User = {
username: "mingddo",
password: "1234"
}
|
🐥 함수에 인터페이스 적용
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
| interface Login {
(username: string, password: string): boolean;
}
let login: Login;
login = (username: string, password: string) => {
// 로그인 로직
return username === "mingddo" && password === "1234";
};
console.log(login("mingddo", "1234")); // true
interface IPerson {
name: string;
age: number;
}
const averageAge = (people: IPerson[]): number => {
return people.reduce((acc, person) => acc + person.age, 0) / people.length;
};
const average = averageAge([
{ name: "Mingddo", age: 30 },
{ name: "CutieMingddo", age: 10 },
{ name: "You", age: 50 },
]);
console.log(average); // 30
|
🚀 타입 별칭(Type Aliases)
type 키워드를 사용해 타입을 지정
- 특정 타입에 별명을 붙여 재사용 가능하게 함
- 코드의 가독성 증가
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
| /* 객체 타입에 타입 별칭 */
type Minddo = {
name: string;
age: number;
};
const minddo: Minddo = {
name: "minseok",
age: 25
};
/* 유니언 타입에 타입 별칭 */
type Color = "Red" | "Blue" | "Yellow";
const color: Color = "Red";
/* 함수 타입에 타입 별칭 */
type Stacks = {
name: string;
period: number;
};
const stacks = (stack: Stacks): string => {
return `Name: ${stack.name}, Period: ${stack.period}`;
};
const myStack: Stacks = { name: "Java", period: 8 };
console.log(stacks(myStack)); // Name: Java, Period: 8
|
🚀 Enum
enum은 관련된 값의 집합에 이름을 붙여주는 방법
1️⃣ 숫자 열거형
1
2
3
4
5
6
7
8
9
| enum Direction {
Up,
Down,
Left,
Right
}
let direction: Direction = Direction.Up;
console.log(direction); // 0
|
2️⃣ 문자 열거형
1
2
3
4
5
6
7
8
9
| enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT"
}
let direction: Direction = Direction.Left;
console.log(direction); // "LEFT"
|
3️⃣ 이니셜라이즈된 열거형 (Const Enum)
const enum은 컴파일 타임 상수로 최적화되는 열거형
const enum
은 런타임에 실제 객체로 존재하지 않음
- 컴파일 시점에 열거형 값이 상수로 대체 !
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| const enum HttpStatus {
OK = 200,
BadRequest = 400,
Unauthorized = 401,
NotFound = 404
}
function handleResponse(status: HttpStatus): string {
switch (status) {
case HttpStatus.OK:
return "Request was successful.";
case HttpStatus.BadRequest:
return "Bad request.";
case HttpStatus.Unauthorized:
return "Unauthorized access.";
case HttpStatus.NotFound:
return "Resource not found.";
default:
return "Unknown error.";
}
}
const status = HttpStatus.OK;
console.log(handleResponse(status)); // "Request was successful."
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| function handleResponse(status) {
switch (status) {
case 200 /* OK */:
return "Request was successful.";
case 400 /* BadRequest */:
return "Bad request.";
case 401 /* Unauthorized */:
return "Unauthorized access.";
case 404 /* NotFound */:
return "Resource not found.";
default:
return "Unknown error.";
}
}
var status = 200 /* OK */;
console.log(handleResponse(status)); // "Request was successful."
|
- 컴파일 타임에 상수 값으로 대체되어, 성능 최적화 가능
- But, 디버깅 시에 원래 열거형 이름 확인 불가
4️⃣ 문자열 및 숫자 혼합 열거형
1
2
3
4
5
6
7
| enum Mixed {
No = 0,
Yes = "YES"
}
console.log(Mixed.No); // 0
console.log(Mixed.Yes); // "YES"
|
🚀 제네릭
코드 작성 시점이 아닌 사용 시점에 타입을 정의하는데 이러한 점은 재사용 가능한 컴포넌트를 작성할 때 유용하고 타입 안정성을 유지하면서 유연하게 작성할 수 있음
1️⃣ 제네릭 함수
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| const identity = <T>(value: T): T => {
return value;
};
// 호출 시점 타입 지정 !
let output1 = identity<string>("myString");
let output2 = identity<number>(123);
console.log(output1); // "myString"
console.log(output2); // 123
// 타입 추론
console.log(identity(42)); // 42
console.log(identity("hello")); // "hello"
|
2️⃣ 제네릭 인터페이스
1
2
3
4
5
6
7
8
9
10
| interface PlayerIdentityFn<T> {
(arg: T): T;
}
const playerIdentity: PlayerIdentityFn<string> = (playerName) => {
return playerName;
};
console.log(playerIdentity("Marcus Rashford")); // Marcus Rashford
console.log(playerIdentity("Bruno Fernandes")); // Bruno Fernandes
|
3️⃣ 제네릭 클래스
1
2
3
4
5
6
7
8
9
10
11
12
13
| class PlayerStats<T> {
initialStat: T;
add: (x: T, y: T) => T;
constructor(initialStat: T, add: (x: T, y: T) => T) {
this.initialStat = initialStat;
this.add = add;
}
}
const goalStats = new PlayerStats<number>(0, (x, y) => x + y);
console.log(goalStats.add(goalStats.initialStat, 5)); // 5
|
4️⃣ 제네릭 제약 조건
1
2
3
4
5
6
7
8
9
10
11
| interface Player {
name: string;
goals: number;
}
const printPlayerGoals = <T extends Player>(player: T): T => {
console.log(`${player.name} has scored ${player.goals} goals.`);
return player;
};
printPlayerGoals({ name: "Marcus Rashford", goals: 10, team: "Man Utd" });
|
- Player 인터페이스는
name
, goals
두 개의 속성을 가짐
printPlayerGoals
함수는 제네릭 타입 변수 T
를 사용하며, 이 제네릭 타입은 Player 인터페이스를 확장함
- ➡️
T
는 Player 인터페이스와 동일하거나 이를 확장하는 타입이어야 함
printPlayerGoals
함수를 호출 할 때, Player 인터페이스는 name
과 goals
속성만 포함하고 있기때문에 함수에서 player.team
에 접근하려 하면 타입스크립트는 team
속성이 인터페이스에 정의되어 있지 않아 에러가 발생하는데 이러한 것이 타입 제약이라고 함