(*ᴗ͈ˬᴗ͈)ꕤ*.゚ 2022. 6. 29. 14:37

1. Call Signature

// ERR -> a, b가 any타입이기 때문
function add(a, b){
  return a + b;
}

// ALLOWED
function add(a:number, b:number){
  return a + b;
}

// ALLOWED
const add = (a:number, b:number) => a+b

// Call signatures
type Add = (a:number, b:number) => number;

const add:Add = (a,b) => a + b

// Call signature 에러 조심 (중괄호)
const add:Add = (a,b) => {a + b} // -> void

2. Overloading(오버로딩)

여러 개의 Call Signatures를 가질 때 주로 발생

// Allowed
type Add = {
    (a: number, b: number): number
}

const add: Add = (a, b) => a + b

// Err
type Add = {
    (a: number, b: number): number
    (a: number, b: string): number
}

const add: Add = (a, b) => a + b

// Allowed
type Add = {
    (a: number, b: number): number
    (a: number, b: string): number
}

const add: Add = (a, b) => {
    if(typeof b === "string") return a
    return a + b
}

 

2-1. Next.js

// Next.js에서의 활용 사례
Router.push({
    path: "/home",
    state: 1
})

.push("/home")
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, config.state)
    }
}

 

2-2. arguments가 다를 때

type Add = {
    (a: number, b: number): number
    (a: number, b: number, c:number): number
}

// case 1 -> ERR
const add:Add = (a, b, c) => {
    return a + b
}

// case 2 -> ERR
const add:Add = (a, b, c:number) => {
    return a + b
}

// case 3 -> Allowed
const add:Add = (a, b, c?:number) => {
    return a + b
}

// case 4 -> Allowed
const add:Add = (a,b,c?:number) => {
    if(c) return a + b + c
    return a + b
}

3. Polymorphism (다형성) // Generics

// 예시

type SuperPrint = {
    (arr:number[]): void
    (arr:boolean[]): void
    (arr:string[]): void
}

const superPrint: SuperPrint = (arr) => {
    arr.forEach(i => console.log(i))
}

// Allowed
superPrint([1,2,3,4])
superPrint([true, false, true])
superPrint(["a", "b", "c"])
// ERR
superPrint([1,2,true,false])
// ERR
superPrint([1,2,true,false])

// ERR -> Allowed로 바꾸는 방법 (1) : call signiture 추가
type SuperPrint = {
    (arr:number[]): void
    (arr:boolean[]): void
    (arr:string[]): void
    (arr:(number|boolean)[]): void 
}

// ERR -> Allowed로 바꾸는 방법 (2) : Genireics 사용 ( = Call Signature 생성)
type SuperPrint = {
    <TypePlaceholder>(arr:TypePlaceholder[]): void
    
}
// Allowed

type SuperPrint = {
    <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])

 

any와 generic 공통점

- 어떤 타입이든 받을 수 있다

 

any와 generic 차이점

- any: 함수를 반환하는 데 있어서 받았던 인수들의 타입을 활용하지 못한다

- generic: 타입에 대한 정보를 다른 쪽으로 전달할 수 있다

 

두 개의 arguments

type SuperPrint = <T, M>(a: T[], b:M) => T

const superPrint : SuperPrint = (a) => a[0]

// Allowed
const a = superPrint([1, 2, 3, 4], "x")

//Expected 2 arguments, but got 1.
const b = superPrint([true, false, true])

 

function으로 표현

function superPrint<V>(a: V[]){
    return a[0]
}

// ALLOWED
const a = superPrint([1, 2, 3, 4])

// ERR (Gererics로 선언했으나, number이라 덮어쓰기 했으므로...)
const b = superPrint<number>([true, false, true])

 

활용법

type Player<E> = {
    name: string
    extraInfo: E 
}

const nico : Player<{favFood: string}> = {
    name: "nico",
    extraInfo: {
        favFood: "kim"
    }
}
type Player<E> = {
    name: string
    extraInfo: E 
}

type NicoPlayer = Player<{favFood: string}>

const nico : Player<{favFood: string}> = {
    name: "nico",
    extraInfo: {
        favFood: "kim"
    }
}
type Player<E> = {
    name: string
    extraInfo: E 
}

type NicoExtra = {
    favFood: string
}
type NicoPlayer = Player<NicoExtra>

const nico : Player<{favFood: string}> = {
    name: "nico",
    extraInfo: {
        favFood: "kim"
    }
}