poly : many, multi
morpho : form, structure
=> many different forms
concrete type : number, void, boolean 등 지금까지 배운 타입.
generic type : 타입 placeholder
type SuperPrint = {
(arr: number[]): void)
}
const superPrint: SuperPrint = (arr) => {
arr.forEach(i => console.log(i))
}
이 때,
superPrint(1, 2, 3, 4)//은 가능하다.
//하지만
superPrint(1, 2, true, "4") //처럼 모든 타입에 대해 함수를 호출하고 싶다고 해서
type SuperPrint = {
(arr: number[] | string[] | boolean[]): void
} //이렇게 or로 일일히 써주는 것보단 generic을 사용해주는게 좋다.
즉, call signature를 작성할 때, 확실한 타입을 모를 경우에 generic type을 사용한다.
그럴 땐 먼저 타입스크립트에게 generic을 사용하겠다고 말해줘야 한다.
type SuperPrint = {
<TypePlaceholder>(arr: TypePlaceholder[]): void
//<>를 아무 이름과 함께 적어주어 generic을 사용하겠다고 말해줌.
//그리고 타입의 이름도 같은 것으로 적어줌.
}
const superPrint: SuperPrint = (arr) => {
arr.forEach(i => console.log(i))
}
superPrint(1, 2, 3, 4)
//이제 superPrint함수에 마우스를 올려보면 위에 generic으로 적은 call signature가 나오는 걸 볼 수 있다.
//타입스크립트가 알아서 number array라는걸 유추해서 placeholder를 대체해 call signature로 알려주게 된다.
보통 간략하게
<T> 또는 <V> 로 줄여쓴다.
type SuperPrint = {
<T>(arr: T[]): T
//이제 void가 아니라 배열을 return하는 함수기 때문에 void대신 TypePlaceholder를 리턴한다고 적어준다.
}
const superPrint: SuperPrint = (arr) => arr[0]
const a = superPrint([1, 2, 3, 4])// const a: number
const b = superPrint([true, false, true])// const b: boolean
const c = superPrint(["a", "b", "c"])// const c: string
const d = superPrint([1, 2, true, false, "hi"])// const d: string|number|boolean
type SuperPrint = <T, M>(a: T[], b: M) => T
const superPrint: SuperPrint = (a, b) => a[0]
a = superPrint([1, 2], "b")