JavaScript

TypeScript 2

재키재키 2022. 6. 12. 14:35

1. call signatures

  • TypeScirpt에서 함수를 작성할 때에 항상 parmeter type과 return type을 함께 정의해야 한다.
  • call signature 즉 미리 함수에 대해 type을 작성하고 이후에 함수를 만들어 사용할 수 있다. 

 

// 함수의 return type을 적지 않아도 된다, 
const add1 = (a:number, b:number) => a + b

// call signatures : 함수에 마우스 올렸을 때 함수에 대해 알려주는 거
// 함수의 타입을 정의할 수 있다. 이는 parmeter, return 의 type을 미리 정의함을 말한다. 
type Add = (a:number, b:number) => number
const add2:Add = (a, b) => a + b

 

 

2. overloading

  • 여러개의 서로 다른 call signature를 가진 함수 
  • 함수에 여러가지 방법으로 parameter를 전달하고 싶을 때 
  • parmeter의 개수가 달라지면 ?(optional)임을 명시해야 한다. 
// overloaing
// 여러개의 서로 다른 call signatures를 가진 함수

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
}

// example 
// nextjs : 밑의 두 함수는 서로 다른 parameter값으로 정확히 같은 일을 한다. 
Router.push({
    path:"/home"
})
Router.push("/home")

type Config = {
    path: string,
    staet: 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.staet)
    }    
}

// 만약에 parmeter의 개수가 다른 call signature라면?
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
}

add(1, 2)
add(1, 2, 3)

 

3. polymorphism, generic

  • generic을 사용하면 함수가 concerte type이 아닌 아닌 parameter를 받을 때 상황에 맞게 정의될 수 있게 한다. 
  • generic은 call signature를 요구하는 대로 매번 다르게 알아서 정의해준다. 
  • parameter를 any로 지정하는 것과는 다르다 
  • type SuperPrint = <T>(a: T[]) => T
  • 여러개의 generic을 사용할 때에는 정의하고 순서에 맞게 paameter를 넣어주면 된다, 
// polymorphism, generic

type SuperPrint = {
    // (arr: number[]): void
    // (arr: boolean[]): void,
    // (arr: string[]): void,
    // (arr: (number|string|boolean)[]): void
    // 모두 이렇게 정의해야 한다고??
    // generic 사용하자! -> 함수가 concrete type이 아닌 generic을 받을 때 
    <T>(arr: T[]): void
}

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

// type script가 매번 다르게 call signature를 유추해서 알려준다. 
superPrint([1,2,3,4])
superPrint([true, false, true])
superPrint(["a", "b", "C"])
superPrint([1, 2, "a", true])

type SuperPrint2 = {
    <T>(arr: T[]): T // generic 사용1 
}

const superPrint2:SuperPrint = (arr) => arr[0]

const x = superPrint2([1,2,3])
const y = superPrint2([true, false, true])
const z = superPrint2(["a", "b", "C"])

// 여러개의 generic 사용, 순서에 맞게 parameter를 넣어준다. 
type SuperPrint3 = <T, V>(a:T[], b:V) => T

const superPrint3: SuperPrint3 = (a,b) => {
    console.log(b)
    return a[0]
    }

const x = superPrint3([1,2,3],"many generic")

 

  • 더 많은 사용예시들.... 
// generic...
function superPrint<T>(a: T[]){
    return a[0]
}

// generic을 사용! 아직 E는 정해지지 않았다. 
type Player<E> = {
    name: string,
    extraInfo: E,
}

// generic E는 객체라고 알려주자. 
const joony: Player<{favFood:string}> = {
    name:"joony",
    extraInfo: {
        favFood: "hambe"
    }
}

type JoonyExtra = {
    favFood: string
}

// generic E가 JoonyExtra type이다!
type JoonyPlyaer = Player<JoonyExtra>

const hanbi: JoonyPlyaer = {
    name: "hanbi",
    extraInfo: {
        favFood:"gimch"
    }
}

type A = Array<number>
let a:A = [1,2 , 3]

function printAllNumbers(arr: Array<number>){

}