[TypeScript] Type Generic
์นดํ
๊ณ ๋ฆฌ : ํ๋ก๊ทธ๋๋ฐ ์ธ์ด
ํ๊ทธ: ts · typescript · Type Generic · Type Inference · ํ์ ์ถ๋ก · ํ์ ํ๋ช
ํ๊ทธ: ts · typescript · Type Generic · Type Inference · ํ์ ์ถ๋ก · ํ์ ํ๋ช
1. Generic : ์ ๋ค๋ฆญ์ด๋ ํ์ ์ ๋ง์น ํจ์์ ํ๋ผ๋ฏธํฐ์ฒ๋ผ ์ฌ์ฉํ๋ ๊ฒ
- ์ ๋ค๋ฆญ์ C#, Java ๋ฑ์ ์ธ์ด์์ ์ฌ์ฌ์ฉ์ฑ์ด ๋์ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค ๋ ์์ฃผ ํ์ฉ๋๋ ํน์ง์ ๋๋ค. ํนํ, ํ๊ฐ์ง ํ์ ๋ณด๋ค ์ฌ๋ฌ ๊ฐ์ง ํ์ ์์ ๋์ํ๋ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ๋๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
1) ์ ๋ค๋ฆญ ํ์ฉํ๊ธฐ
- Generic ๊ธฐ๋ณธ ๋ฌธ๋ฒ ์ ๋ฆฌ
- V : value
- T : type
- K : key
- E : element
function genericTest<T>(arg: T): T {
return arg;
}
genericTest<string>("Hello World!");
genericTest("Hello World!"); // ํ์
์ถ๋ก
์ฌ์ฉ ์ด์
- ํ์ ์ ๋ฏธ๋ฆฌ ์ง์ ํ๊ฒ ๋๋ฉด ๋ฒ์ฉ์ฑ์ด ๋จ์ด์ง
- any๋ฅผ ์ฐ๋ฉด return ํ์ ๊ณผ parameter ํ์ ์ ์ ์ ์์.
- ์ ๋ค๋ฆญ ํ์ ๋ณ์(Generic Type Variables)
function genericTest<T>(arg: T): T {
console.log(arg.length); // error: 'T' ํ์์ 'length' ์์ฑ์ด ์์ต๋๋ค.
return arg;
}
/* T(ํ์
๋ณ์)์ ๋ํ ์ธ๋ถ์ ์ธ ๋ณ์ ํ์
์ ์ง์ */
function genericTest<T>(arg: T[]): T[] {
console.log(arg.length);
return arg;
}
=> genericTest๋ ํ์
๋ณ์ T์ T ๋ฐฐ์ด ์ธ์ arg๋ฅผ ์ทจํ๊ณ T ๋ฐฐ์ด์ ๋ฐํ
- ์ ๋ค๋ฆญ ํ์ (Generic Types)
function genericTest<T>(text: T): T {
return text;
}
// #1
let str: <T>(text: T) => T = genericTest;
// #2
// let str: {<T>(text: T): T} = genericTest;
=> #1,#2๋ ๊ฐ์ ์๋ฏธ์.
- ์ ๋ค๋ฆญ ์ธํฐํ์ด์ค (Generic Interface)
interface IGenericTestFn {
<T>(text: T): T;
}
function genericTest<T>(text: T): T {
return text;
}
let myString: IGenericTestFn = genericTest;
T๋ ์ ๋ค๋ฆญ์ ์ ์ธํ ๋ ๊ด์ฉ์ ์ผ๋ก ์ฌ์ฉ๋๋ ์๋ณ์๋กย ํ์ ํ๋ผ๋ฏธํฐ(Type parameter)
/* ์ธํฐํ์ด์ค์ ์ธ์ ํ์
์ ๊ฐ์กฐ ํ๊ณ ์ถ์ ๋ */
interface IGenericTestFn<T> {
(text: T): T;
}
function genericTest<T>(text: T): T {
return text;
}
let myString: IGenericTestFn<string> = genericTest;
- ์ ๋ค๋ฆญ ํด๋์ค (Generic Classes)
interface Value<L,R> {
callLeft: () => L;
callright: () => R;
}
class Diary<L,R> implements Value<L,R> {
//implements ํค์๋๋ class์ interface์ ๋ง์กฑํ๋์ง ์ฌ๋ถ๋ฅผ ์ฒดํฌํ ๋ ์ฌ์ฉ
//implementsํ interface์ ํ์
์ด ์๋ค๋ฉด ์๋ฌ๋ฅผ ๋ฐํ
constructor(private feeling: L, private shortWords: R){}
//private์ผ๋ก ํด๋์ค ๋ด๋ถ์์๋ง ์ฐธ์กฐ ๊ฐ๋ฅํ๋ค.
callLeft(): L {
console.log(this.feeling);
return this.feeling
}
callright(): R {
console.log(this.shortWords);
return this.shortWords
}
}
const yesterdayDiary: Value<string, string> = new Diary("Bad", "๋ชธ์ด ์ํ๋ค์");
//์์ฑ์ ํธ์ถ
console.log(yesterdayDiary);
const todayDiary = new Diary({"happy": 10}, "๋ก๋ ๋น์ฒจ");
//์์ฑ์ ํธ์ถ
console.log(todayDiary);
=> ๊ฒฐ๊ณผ๊ฐ
Diary { feeling: 'Bad', shortWords: '๋ชธ์ด ์ํ๋ค์' }
Diary { feeling: { happy: 10 }, shortWords: '๋ก๋ ๋น์ฒจ' }
- ์ ๋ค๋ฆญ ์ ์ฝ์กฐ๊ฑด (Generic Constraints)
interface Info {
feeling: string;
}
function call<T extends Info>(today: T): T {
console.log(today.feeling);
return today;
}
call({ feeling: "good" });
call("good"); // Argument of Type 'string' is not assignable to paramerter of type 'Info'
๋ฌธ์์ด ํ์ ์ ์ธ์๋ Info ํ์ ์ ๋งค๊ฐ๋ณ์์ ํ ๋นํ ์ ์๋ค๋ ์ค๋ฅ
Info ์ธํฐํ์ด์ค๋ฅผ ํ์ฅํ์๊ธฐ ๋๋ฌธ์, ์ ์๋ ์ธํฐํ์ด์ค์ ์ผ์นํด์ผํจ.
any๋ฅผ ์ด์ฉํ์ฌ ๊ตฌํํ๋ฉด ์ ์ฅํ๊ณ ์๋ ์๋ฃ์ ํ์ ์ด ๋ชจ๋ ๊ฐ์ง ์๋ค๋ ๋ฌธ์ ์ ์ด ์๊ธฐ๋๋ฐ, ์ด๋ฅผ ์ฌ์ฉํ๋ฉด ๊ตณ์ด ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ์ธ ํ์๊ฐ ์๋ค