드림코딩엘리님의 TypeScript 강의를 토대로 정리했습니다.
const num: number = 1;
const str: string = 'hello';
const bool: boolean = false;
undefined
타입 지정은 모순적이다.undefined
라는 것이 의미적으로 앞뒤가 맞지 않는다.undefined
로 선언된 변수에는 undefined
외에는 지정이 불가하다.let name: undefined; // 💩 not good -> useless
name = 'Hwibaski' // error
타입이
string
일 수도 있고,undefined
일 수도 있다면union type
을 사용하자.
let age: number | undefined;
age = undefined;
age = 1;
// find 함수는 number를 리턴할 수도 있고, undefined를 리턴할 수도 있다.
const find = function (): number | undefined {
return 1 || undefined;
};
null
은 undefined
와 비슷한 맥락으로 값이 없다는 것이지만 명시적으로(의도적으로) 값이 없음을 나타낸다.let person: null; // 💩 not good -> useless
let person2: string | null;
person = null;
person2 = 'hello';
let notSure: unknown = 0;
notSure = 'he';
notSure = true;
let anything: any = <0;
anything = 'hello';
anything = 1;
unknown
과any
는 사실상 typescript를 사용하는 의미를 퇴색시킨다. 정말 필요한 곳 외에는 사용을 지양하자.
// void : 아무것도 리턴하지 않는다, 다만 리턴문은 한다.
function print(): void {
console.log('hello');
return;
}
// return 문이 없지만 내부적으로 return undefined가 생략되어 있으므로
// 아무것도 void 타입이다.
function print(): void {
console.log('hello');
// return undefined -> return문이 없을 시,
// JavaScript 내부적으로 return undefined를 한다.
}
void
void
타입을 지정하면 undefined
만 할당이 가능하기 때문에, 활용성이 떨어진다.let useless: void = undefined; // 💩
let useless = '123' // error
void
타입은 아무것도 리턴을 하지 않을 때 사용을 했다.never
타입은 return 자체를 하지 않을 때 사용을 한다.throw new Error()
와 같은 에러 핸들링에 사용된다.// never : return 자체를 하지 않는다.
function throwError(message: string): never {
// message => server (log)
// 1 : error 핸들링의 경우
throw new Error(message);
// 2 : 무한 루프 역시 아무것도 리턴하지 않으므로 never 타입이다.
while (true) {
// ...
}
}
// 이런 식으로 사용하는 경우는 없다.
let neverEnding: never; // 💩
object
타입을 지정할 수 있다.object
타입을 지정할 경우, 너무 광범위한 값들이 올 수 있기 때문에 썩 좋은 타입은 아니다.let obj: object; // 💩
obj = [1, 2, 3]
obj = { test: 'test'}
function acceptSomeObject(obj: object) {} //
// 💩 -> 어떠한 객체(배열)이든 받아들을 수 있다. 너무 광범위 하다...
acceptSomeObject({ name: 'hwimin' });
acceptSomeObject({ animal: 'dog' });
// JavaScript
function jsAdd(num1, num2) {
return num1 + num2;
}
// TypeScript
function add(num1: number, num2: number): number {
return num1 + num2;
}
// JavaScript
function jsFetchNum(id) {
// code..
// code..
return new Promise((resolve, reject) => {
resolve(100);
});
}
// TypeScript
// string인 id를 받아서 Promise를 return 하는데,
// resolve 시 값이 number이다.
function fetchNum(id: string): Promise<number> {
// code ...
return new Promise((resolve, reject) => {
resolve(100);
});
}
optional parameter
를 사용한다.lastName
매개변수는 string
일 수도 있고, undefined
일 수도 있다.parameter?: type
function printName(firstName: string, lastName?: string) {
console.log(firstName);
console.log(lastName);
}
printName('Steve', 'Jobs'); // 'Steve', 'Jobs'
printName('Hwimin'); // 'Hwimin', undefined
printName('Anna', undefined); // 'Anna', undefined
printName('Anna', 123) // error
lastName
매개변수만 union type
으로 지정해보자optional parameter
대신 union 타입
을 사용 시, 무조건 특정한 값이 있어야 한다.undefined
로 명시해줘야하므로, 유연하지 못하고 불필요한 코드도 생성된다.function printName(firstName: string, lastName: string | undefined) {
console.log(firstName);
console.log(lastName);
}
printName('Steve', 'Jobs'); // 'Steve', 'Jobs'
printName('Hwimin'); // error -> why? union type으로 지정 시 무조건 값이 있어야한다.
printName('Hwimin', undefined); // 'Hwimin', undefined
printName('Anna', undefined); // 'Anna', undefined
printName('Anna', 123) // error
default parameter
를 사용할 수 있다.function printMessage(message: string = 'default message') {
console.log(message);
}
// 아무 인수도 넣지 않았지만, 'default message'가 출력된다.
printMessage(); // 'default message'
...parameter
의 형태로 매개변수를 지정하고, 인수로 여러 개의 값들을 입력할 시 parameter에 인수의 값들이 배열로 저장된다.const add = function(...numbers) {
console.log(numbers);
}
add(2, 3) // [2, 3]
add(5, 3, 7, 2) // [5, 3, 7, 2]
add(8, 2, 5, 3, 2, 1, 4) // [8, 2, 5, 3, 2, 1, 4]
...parameter
의 타입을 지정해 줄 수 있다. 즉, 매개변수로 들어올 배열들의 각 요소의 타입을 지정할 수 있다.// JavaScript
function addNumbers(...numbers) {
return numbers.reduce((a, b) => a + b);
}
// TypeScript
function addNumbers(...numbers: number[]): number {
return numbers.reduce((a, b) => a + b);
}
console.log(addNumbers(1, 2)); // 3
console.log(addNumbers(1, 2, 3, 4)); // 10
console.log(addNumbers(1, 2, 3, 4, 5, 0)); // 15
console.log(addNumbers(1, '1')); // compile error
addNumbers
의 인수에 문자열을 넣어보자.// JavaScript
function addNumbers(...numbers) {
return numbers.reduce((a, b) => a + b);
}
console.log(addNumbers(1, '1')) // '11' -> 끔찍하다.
const alphabet: string[] = ['a', 'b'];
const alphabet: Array<string> = ['a', 'b'];
readonly
의 사용가능 여부가 다르다.readonly
사용가능readonly
사용불가 ** readonly를 구현하는 방법 **
const alphabet1: readonly string[] = []
const alphabet2: ReadonlyArray<string> =[]
const alphabet3: Readonly<string[]> = []
readonly
란?// readonly를 추가할 경우 매개변수 alphabet의 값을 읽을 수만 있다.
// alphabet의 값을 수정할 수 없다.
// alphabet.push() 같은 메서드를 pirntArray 함수 내부에서
// 사용할 수가 없다는 뜻이다.
function printArray(alphabet: readonly string[]) {}
💡
-> 취향껏 사용하자readonly
가 굉장히 많이 쓰이기 때문에 1번 방법을 사용하자!
Tuple
이란?let student: [string, number];
student = ['name', 123];
student[0]; // name
student[1]; // 123
tuple
의 사용은 권장되지 않는다. -> 드림코딩 엘리님의 의견
- 인덱스에 따라 값을 찾는다. 이는 어떤 값이 있는지 파악하기가 어렵다.
- 게다가 각 요소의 타입도 통일되어 있지 않다.
tuple
을 사용할만한 곳에는interface
,type alias
,class
로 대체해서 사용한다.array 구조분해
로 가독성을 높힐 수는 있지만, 굳이?React Hook
,useState()
가 tuple의 좋은 사용 예- 동적으로 관리해야하는 것이 있는데
interface
,type alias
,class
로 관리하기 어렵다면tuple
을 사용한다.
https://academy.dream-coding.com/courses/typescript
https://yamoo9.gitbook.io/typescript/
도서 타입스크립트 프로그래밍