함수에 어떠한 타입이 올 지 모를 때 <>
를 사용하여 타입을 지정합니다.
타입의 이름은 자유롭게 작성 가능하며 관례상 대문자로 작성합니다.
function createPromise<T> (x: T, timeout: number) {
return new Promise((resolve: (v: T) => void, reject) => { // T 는 Type 의 줄임말
setTimeout(() => {
resolve(x);
}, timeout)
})
}
createPromise<string>("eh", 100)
.then(v => console.log(v))
createPromise<number>(1, 100)
.then(v => console.log(v))
function createTuple2<T, U>(v: T, v2: U): [T, U] {
return [v, v2];
}
function createTupl3<T1, T2, T3>(v: T1, v2: T2, v3: T3): [T1, T2, T3] {
return [v, v2, v3];
}
const t1 = createTuple2("user1", 1000); // = ["user1", 1000]
클래스에 generic 타입을 적용하여 좀 더 재활용이 가능한 타입의 클래스 작성
아래의 코드는 오직 User 타입의 값만 적용 가능하도록 함
interface User { name: string }
class LocalDB {
constructor(private localStorageKey: string) { }
add(v: User) {
localStroage.setItem(this.localStorageKey, JSON.stringify(v))
}
get(): User {
const v = localStorage.getItem(this.localStorageKey);
return (v) ? JSON.parse(v) : null;
}
}
그러나 generic 한 타입을 적용하면 좀 더 재활용이 가능한 코드 작성 가능
class LocalDB<T> {
constructor(private localStorageKey: string) { }
add(v: T) {
localStroage.setItem(this.localStorageKey, JSON.stringify(v))
}
get(): T {
const v = localStorage.getItem(this.localStorageKey);
return (v) ? JSON.parse(v) : null;
}
}
interface User { name: string }
const userDb = new LocalDB<User>("user");
userDb.add({ name: "dog" });
인터페이스 또한 generic을 사용할 수 있으며 T타입의 범위를 지정할 수 있다.
T 타입의 JSONserialier 인터페이스를 지정하면 해당 인터페이스의 선언된 범위도 값도 사용 가능
interface DB<T> {
add(v: T): void;
get(): T;
}
interface JSONserialier {
serialize(): string;
}
class LocalDB<T extends JSONserialier> implements DB<T> {
constructor(priavate localStorageKey: string) { }
add(v: T) {
localStorage.setItem(this.localStorageKey, v.serialize())
}
get(): T {
const v = localStroage.getItem(this.localStroageKey);
return (v) ? JSON.parse(v) : null;
}
}