타입 앨리어스는 새로운 타입을 정의한다.
타입으로 사용할 수 있다는 점에서 인터페이스와 유사하다.
interface Person {
name: string,
age?: number
}
// 빈 객체를 Person 타입으로 지정
const person = {} as Person;
// 아래와 동일하다 ------
type Person = {
name: string,
age?: number
}
// 빈 객체를 Person 타입으로 지정
const person = {} as Person;
인터페이스와 다르게 원시값, 유니온 타입, 튜플 등도 타입으로 지정할 수 있다.
// 문자열 리터럴로 타입 지정
type Str = 'Lee';
// 유니온 타입으로 타입 지정
type Union = string | null;
// 문자열 유니온 타입으로 타입 지정
type Name = 'Lee' | 'Kim';
// 숫자 리터럴 유니온 타입으로 타입 지정
type Num = 1 | 2 | 3 | 4 | 5;
// 객체 리터럴 유니온 타입으로 타입 지정
type Obj = {a: 1} | {b: 2};
// 함수 유니온 타입으로 타입 지정
type Func = (() => string) | (() => void);
// 인터페이스 유니온 타입으로 타입 지정
type Shape = Square | Rectangle | Circle;
// 튜플로 타입 지정
type Tuple = [string, boolean];
const t: Tuple = ['', '']; // Error
❗️ NOTE
타입 앨리어스는 extends / implements 될 수 없다.
상속을 통한 확장이 필요한 경우에는 인터페이스가 유리하다. 반면에, 인터페이스로 표현 불가하거나 유니온/튜플 등을 사용해야한다면 타입 앨리어스를 사용하는 것이 유리하다.
제네릭은 선언 시점이 아니라 생성 시점에 타입을 명시하여 다양한 타입을 사용할 수 있도록 하는 기법이다. 동일한 클래스의 프로퍼티를 여러 타입에 대해 사용하고자 할 때 매번 상속-구현을 하지않고 한 번의 선언으로 재사용할 수 있는 이점이 있다.
class Queue<T> {
protected data: Array<T> = [];
push(item: T) {
this.data.push(item);
}
pop(): T | undefined {
return this.data.shift();
}
}
const numberQueue = new Queue<number>(); // number 전용 큐
const stringQueue = new Queue<string>(); // string 전용 큐
const myQueue = new Queue<{name: string, age: number}>(); // 커스텀 객체 전용 큐
타입 파라미터 T
는 제네릭을 선언할 때 관용적으로 사용되는 식별자로써, 반드시 T를 사용해야하는 것은 아니다.
함수에도 제네릭을 사용할 수 있다.
function reverse<T>(items: T[]): T[] {
return items.reverse();
}
const arg = [1, 2, 3, 4, 5];
// 인수에 의해 타입 매개변수가 결정된다.
const reversed = reverse(arg);
console.log(reversed); // [ 5, 4, 3, 2, 1]