Generics, Any 차이점
function helloString(message: string): string {
return message;
}
function helloNumber(message: number): number {
return message;
}
function hello(message: any): any {
return message;
}
console.log(hello("Anna").length);
console.log(hello(20).length);
function helloGeneric<T>(message: T): T {
return message;
}
console.log(helloGeneric("Jennie"));
// function helloGeneric<"Jennie">(message: "Jennie"): "Jennie"
// 리터럴 타입으로 추론
console.log(helloGeneric("Jennie").length);
// (property) String.length: number
console.log(helloGeneric(20));
// function helloGeneric<20>(message: 20): 20
console.log(helloGeneric(20).length);
// Error!
// '20' 형식에 'length' 속성이 없습니다.ts(2339)
console.log(helloGeneric(true));
// function helloGeneric<true>(message: true): true
Generics Basic
function helloBasic<T>(message: T): T {
return message;
}
helloBasic<string>(20);
// Error!
// 'number' 형식의 인수는 'string' 형식의 매개 변수에 할당될 수 없습니다.ts(2345)
helloBasic<string>("Hello");
helloBasic(33);
// function helloBasic<33>(message: 33): 33
function helloBasic<T, U>(message: T, comment: U): T {
return message;
}
helloBasic<string, number>("Hello", 20);
helloBasic(33, 40);
Generics Array & Tuple
function helloArray<T>(message: T[]): T {
return message[0];
}
helloArray(["Hello", "World"]);
// function hellloArray<string>(message: string[]): string
helloArray(["Hello", 7]);
// function hellloArray<string | number>(message: (string | number)[]): string | number
function helloTuple<T, K>(message: [T, K]): T {
return message[0];
}
helloTuple(["Hello", "World"]);
// function helloTuple<string, string>(message: [string, string]): string
helloTuple(["Hello", 7]);
// function helloTuple<string, number>(message: [string, number]): string
Generics Function
type HelloFunctionGeneric1 = <T>(message: T) => T;
const helloFunction1: HelloFunctionGeneric1 = <T>(message: T): T => {
return message;
};
interface HelloFunctionGeneric2 {
<T>(message: T): T;
}
const helloFunction2: HelloFunctionGeneric2 = <T>(message: T): T => {
return message;
};
Generics Class
class Person<T, K> {
private _name: T;
private _age: K;
constructor(name: T, age: K) {
this._name = name;
this._age = age;
}
}
new Person("Mark", 39);
new Person<string>(30);
// Error! 'number' 형식의 인수는 'string' 형식의 매개 변수에 할당될 수 없습니다.ts(2345)
new Person<string, number>("Mark", "age");
// Error! 'string' 형식의 인수는 'number' 형식의 매개 변수에 할당될 수 없습니다.ts(2345)
Generics with extends
class PersonExtends<T extends string | number> {
private _name: T;
constructor(name: T) {
this._name = name;
}
}
new PersonExtends('Mark');
new PersonExtends(30);
keyof & type lookup system
interface IPerson {
name: string;
age: number;
}
const person: IPerson = {
name: "Mark",
age: 38
};
function getProp<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
getProp(person, 'name');
getProp(person, 'age');
function setProp<T, K extends keyof T>(obj: T, key: K, value: T[K]): void {
obj[key] = value;
}
setProp(person, "name", "Anna");
setProp(person, "age", 20);