Typescript 문서 - 06
Generics
C# 및 Java와 같은 언어에서 재사용 가능한 구성 요소를 작성하기 위한 기본 도구 중 하나가 Generic이다. 즉, 다양한 타입에서 작동할 수 있는 구성 요소를 만들 수 있어야 한다.Hello World of Generics
함수를 정의할 때 모든 타입을 수용하게 하는 방법은any 타입을 사용하는 것이지만, any 타입을 사용하게 되면 함수가 리턴할 때 그 타입이 어떤 것인지 정보를 모르게 된다.따라서, Type 변수를 사용해보자.
function identity<T>(arg: T): T { // Type 변수 T 추가
return arg;
}
T는 사용자가 제공한 타입을 Capture하여 가지고 있다가 나중에 해당 정보를 사용할 수 있도록 해준다. 그리고 리턴 타입으로 사용하고 있다.Generic 함수 호출 방법
- Type 파라미터를 포함한 모든 파라미터를 함수에 전달하는 방법
let output = identity<string>("myString"); // return type: string
- 컴파일러가 전달하는 파라미터의 타입에 따라 자동으로
T의 값을 설정하는 방법(가장 일반적)
let output = identity("myString"); // type: string
// 컴파일러는 "myString"이라는 값을 보고 타입이 string이라고 설정하는 것
// 복잡한 코드에서는 컴파일러가 타입을 추론하지 못할 수도 있으니 타입을 명시적으로 전달해야 할 수도 있다.
Working with Generic Type Variables
function identity<T>(arg: T): T {
console.log(arg.length) // Error: arg는 length가 없다.
return arg;
}
위의 경우에는 .length를 사용하고 싶지만 사용할 수 없다. 배열로 받고 싶을 때에는 아래의 경우처럼 사용하면 된다.function logginIdentity<T>(arg: T[]): T[] {
console.log(arg.length); // Ok: 사용 가능
return arg;
}
또는
function logginIdentify<T>(arg: Array<T>): Array<T> {
console.log(arg.length);
return arg;
}
Generic Classes
Generic 클래스는 클래스 이름 다음에 꺽쇠 괄호, Generic Type 파라미터 목록을 갖는다.class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };
Generic Constraint
맨 처음 예제에서arg.length를 콘솔에 출력해보면 에러가 났다. .length를 사용하고 싶어서 Generic Type을 항상 <arg: T[]>이런 식으로 하면 안된다. 따라서 모든 타입으로 작업하는 대신, .length를 가진 모든 타입과 함께 동작하도록 제한하고 싶을 경우, 아래와 같이 작성하면 된다.interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
loggingIdentity(3); // Error: number는 .length 프로퍼티를 가지고 있지 않다.
loggingIdentify({length: 10, value: 3}); // 대신 필수 프로퍼티가 있는 타입 값을 전달해주어야 한다.
Using Type Parameters in Generic Constraints
이름이 있는 객체로부터 프로퍼티를 얻고 싶을 수 있다. 따라서 obj에 존재하지 않는 프로퍼티를 갖지 않도록 제약 조건을 적용할 수 있다.function getProperty(<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
let x = {a: 1, b: 2, c: 3, d: 4};
getProperty(x, "a"); // Ok
getProperty(x, "m"); // Error: m이라는 프로퍼티는 x 변수에는 없다.
댓글
댓글 쓰기