type Add = (a:number, b:number) => number;
const add:Add = (a, b) => a + b
프로그램을 디자인하면서 타입을 먼저 생각하고 코드를 구현한다.
다른 사람들이 만든 외부 라이브러리를 사용할텐데 그러한 패키지나 라이브러리들이 오버로딩을 많이 사용한다.
오버로딩은 함수가 서로 다른 여러 개의 call signatures를 가지고 있을 때 발생한다.
// 좋은 코드는 아니지만 오버로딩의 예시
type Add = {
(a:number, b:number) : number;
(a:number, b:string) : number;
}
const add:Add = (a, b) => {
if(typeof === 'string') return a
return a + b
}
// 나중에 보게 될 예시 Next.js
type Config = {
path: string,
state: object
}
type Push = {
(path: string): void
(config: Config): void
}
const push: Push = (config) => {
if(typeof config === 'string') { console.log(config) }
else {
console.log(config.path)
}
}
// c는 옵션
type Add = {
(a:number, b:number) :number
(a:number, b:number, c:number) :number
}
const add:Add = (a, b, c?:number) => {
if(c) return a + b + c
return a + b
}
type SuperPrint = {
// Typescript에게 타입을 유추하도록 알려준다.
<TypePlaceholder>(arr: TypePlaceholder[]): TypePlaceholder
}
const superPrint: SuperPrint = (arr) => arr[0]
const a = superPrint([1, 2, 3, 4])
const b = superPrint([true, false, true])
const c = superPrint(["a", "b", "c"])
const d = superPrint([1, 2, true, false, "hello"])
<T, M>(arr: T[], b: M): T
const superPrint: SuperPrint = (arr) => arr[0]
const a = superPrint([1, 2, 3, 4], "x")
// return은 T, M 어느것을 써도 상관 없는 것인가?
// => superPrint 함수의 리턴값에 따라 달라질 수 있다.
type SupserPrint = {
(arr: T[], b?: M): T | M
}
// generic을 추가했는데, arguement를 추가 해야 하는 건 아닌가?
// => uperPrint 함수의 리턴값에 따라 달라진다.
const superPrint: SupserPrint = (arr, m) => {
if (m) { return m }
return arr[0]
}
const a = superPrint([1, 2, 3, 4])
const b = superPrint([false, true, true, true], "2")
const c = superPrint(["1", "2", "3", "4"], 5)
const d = superPrint([2, false, true, 4], "55")