Generic Function
만약 당신이 Java
를 익숙하게 사용하는 개발자라면 이 섹션은 이해하기 정말 쉬울 것이다. 다른 언어에서 흔히들 Generic
이라고 부르는 것과 동일하기 때문이다.
예를 들어, 당신이 Stack
자료구조를 직접 구현한다고 해보자.
Stack
에는 정말로 많은 Type
의 데이터가 들어간다. Number
String
Boolean
와 같은 모든 유형을 포함해야 한다.
class Stack {
private data = [];
public push(item) {
this.data.push(item);
}
public pop() {
return this.data.pop();
}
}
물론 이런 형태로 작성할 수는 있겠으나, 우리가 원하는 Typescript
의 형태를 띄려면 각 Method
와 Paramter
의 Return Type
을 정의해야 한다.
만약 제네릭이 없다면
class NumberStack {
private data: number[] = [];
public push(item: number) {
this.data.push(item);
}
public pop(): number {
return this.data.pop();
}
}
class StringStack {
private data: string[] = [];
public push(item: string) {
this.data.push(item);
}
public pop(): string {
return this.data.pop();
}
}
/// ...
이런 식으로 모든 유형에 대응하는 StackClass를 정의해야 할 것이다.
이건 사실 말이 안되므로, 제네릭을 사용해서 구현을 하면 아래와 같이 표현할 수 있다.
class Stack<T> {
private data: T[] = [];
public push(item: T) {
this.data.push(item);
}
public pop(): T | null {
return this.data.pop() || null;
}
}
class
이름 뒤에 <T>
가 추가 되었다.
이는 Type
을 받을 수 있는 Type Variable
이라고 불린다. 제네릭 타입의 객체를 사용할 때는 아래와 같이 사용하면 된다.
1
const stack: Stack<number> = new Stack<number>();
이렇게 선언하면 number
타입으로 구성 된 Stack
클래스를 사용할 수 있다.
예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Stack<T> {
private data: T[] = [];
public push(item: T) {
this.data.push(item);
}
public pop(): T | null {
return this.data.pop() || null;
}
}
const stack = new Stack<number>();
stack.push(123);
console.log(stack.pop()); // 123
console.log(stack.pop()); // null
두 개 이상의 Type Variable
Type Variable
은 여러개를 선언할 수도 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Stack<T, U> {
private data: [T, U][] = [];
public push(item: [T, U]) {
this.data.push(item);
}
public pop(): [T, U] | null {
return this.data.pop() || null;
}
}
const stack: Stack<number, string> = new Stack<number, stirng>();
stack.push([123, 'hello']);
console.log(stack.pop()); // [123, 'hello']
console.log(stack.pop()); // null
Type 상속
가독성 측면에서 쓸 일이 진짜 없을 것 같지만 가능은 하다고 하니 알아보겠다.
1
2
3
4
5
function getFirst<T extends Stack<U>, U>(container: T): U {
const item = container.pop();
container.push(item);
return item;
}
1
2
getFirst<Stack<number>, number)(numberStack);
getFirst<number, number>(1); // Type 'number' does not satisfy the constraint 'Stack<number>'.