Generics이란?
any는 어떤 타입이 들어오는지 상관없이 때문에 타입마다 잘못된 내부 함수를 사용하거나 타입 추론할 때 유용하지 못하다. 하지만 Generic의 경우에는 컴파일 타임에 타입을 추론하여 return과 parameter의 타입을 추론할 수 있도록 도와준다.
function hello(message: any): any {
return message;
}
console.log(hello("Mark").length);
console.log(hello(39).length); // undefined가 된다.
function helloGeneric<T>(message: T): T {
return message;
}
console.log(helloGeneric('Mark').length);
console.log(helloGeneric(39).length); // 에러발생
정의하는 방법
사용할 때 <>안에 타입을 의미하는 문자를 넣는다.
아래예제에서 T를 사용할 때 특정 타입으로 지정된다면 지정해준 모든 타입이 지정된 타입으로 변하고
지정하지 않더라도 추론된 타입으로 지정된다.
function helloBasic<T>(message: T): T {
return message;
}
helloBasic<string>("Mark");
helloBasic(36);
Array & Tuple
Array
function helloArray<T>(message: T[]): T {
return message[0]
}
helloArray(['Hello1', 'Hello2']);
helloArray(['Hello1', 39, true]);
Tuple
function helloTuple<T, K>(message: [T, K]): T {
return message[0];
}
helloTuple(['Hello1', 'Hello2']);
helloTuple([39, 'Hello']);
function
type
type HelloFunctionGeneric1 = <T>(message: T) => T;
const helloFunction1: HelloFunctionGeneric1 = <T>(message: T): T => {
return message;
};
interface
interface HelloFunctionGeneric2 {
<T>(message: T): T
};
const helloFunction2: HelloFunctionGeneric2 = <T>(message: T): T => {
return message;
};
class
클래스 이름 옆에 클래스 이름을 표시한다. 클래스 내부에서 유효범위를 가지게 된다.
class Person<T> {
private _name: T;
constructor(name: T) {
this._name = name;
}
}
extends를 사용하여 T를 제한할 수 있다.
class Person<T extends string | number> {
private _name: T;
constructor(name: T) {
this._name = name;
}
}
keyof & type lookup system
keyof키워드는 데이터 구조체의 필드를 key type으로 변환시킬 수 있다.
interface IPerson {
name: string;
age: number;
};
type Keys = keyof IPerson; // Keys는 "name", "age"를 가지는 타입이 됨
getter와 setter를 사용할 때 유용하다.
위 코드를 봤을 때 IPerson의 키가 name이면 string을 age면 number를 가지게 된다. 이것을 단순히 유니온으로 표현한다면 잘못사용될 수 있기 때문에 name일때는 string을 age일때는 number를 쓰도록 강제해야만 한다.
변경 전에는 getProp은 문제가 없어보일 수 있지만, return이 될 때, string인지 number인지 확인 할 수 없어 메소드 체인과 같이 return값을 유용하게 사용하지 못한다.
function getProp(obj: IPerson, key: "name" | "age"): string | number {
return obj[key];
}
keyof를 사용해서 K를 "name" | "age"로 강제 한 후 return을 T[K]로 받는다면 return타입이 T[k]의 타입으로 강제된다.
function getProp<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
setter에서는 obj[key]에 넣을 때 정말 obj[key]에 타입에 맞는 값인지 확인 할 수 없기 때문에 에러를 발생시킨다.
function setProp(obj: IPerson, key: "name" | "age", value: string| number): void {
obj[key] = value;
}
keyof를 사용하여 value의 타입을 확정시킬 수 있다.
function setProp<T, K extends keyof T>(obj: T, key: K, value: T[K]): void {
obj[key] = value;
}
'FrontEnd > TypeScript' 카테고리의 다른 글
Class static / 싱글톤 / 상속 / Abstract (0) | 2022.10.09 |
---|---|
Class 정의 / 초기화 / Getter And Setter (0) | 2022.10.08 |
Interface (0) | 2022.10.07 |
TypeScript 컴파일러 (0) | 2022.09.28 |
TypeScript 타입호환성 (0) | 2022.09.27 |
댓글