TS

[TypeScript] Call Signatures, Overloading

코딩하는둥이 2023. 2. 23. 17:45

함수선언

 
1. function 
function add(a:number, b:number): number { // :number 안해도 된다
 return a +b;
}
 
2. 화살표 함수
const add = (a:number, b:number) => a+b

 

 

call signatures

함수를 어떻게 호출해야 하는 것인지 알려준다.
: 함수 위에 마우스를 올렸을 때 보게 되는 것
: 함수의 반환타입 알려줌
: 인자의 타입랑 함수의 반환 타입 알려줌
 

 

call signature 선언 

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

 const add:Add = (a,b) => a+b // 타입 선언을 안해도 타입을 유추할 수 있음
type Add = (a:number,b:number) => number;

 const add:Add = (a,b) =>{ a+b} // 함수는 void 반환하지 않음 number을 반환

 

overloading

 : 함수가 서로 다른 여러개의 call singnature를 가지고 있을떄 발생
 
 
나쁜예시
 
type Add = {
    (a:number, b:number)
    (a:number, b:string)

}

const add: Add = (a,b) =>a+b ; // b가 string 될 수도 있고 number도 될수 있어 못 더해서 에러 발생

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

}

const add: Add = (a,b) =>{
    if(typeof b === "string") return  // b가 string 일때 a와 b를 리턴한다.
    return a+b
}​

 

좋은 예

type Config = {
    path: string,
    state:object
}

type Push = {
  (path:string):void// path string으로 받고 void 리턴
   (config:Config):void// config object config 타입, void 리턴
}
const push: Push = (config) => { // ()안에 path나 Config타입
    if(typeof config === "string") {console.log(config)}
    else{
        console.log(config.path, config.state)
    }
}
// string을 보내거나 config객체 보냄

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);​

 

다형성 Polymorphism

 : 여러가지 다른 구조
 
concrete type:number, blooean, string, void, unknown
generic: 타입의 placeholder => concrete type을 사용하는 것 대신 쓸 수 있
type SuperPrint = {
    // number, blooean, string 배열을 받는 call signature이 3개가 있
    (arr:number[]):void //number배열을 받고 void 리턴 
    (arr:boolean[]):void 
    (arr:string[]):void  
    (arr:(number|boolean)[]):void // 좋은 방법이 아님  => 모든 가능성을 다 조합해서 만든다

 
    }
    
    const superPrint: SuperPrint = (arr) => {
    arr.forEach(i => console.log(i)) //  // 첫번째 조건인 배열을 받아서, 그 배열의 요소를 각각 콘솔로 찍는 작업
}


superPrint([1,2,3,4]) // number 배열
superPrint([true, false, true, true]) // blooean 배열 
superPrint(["1","2","3","4"]) // string 배열
superPrint([1,2,false, true]) //

//
//

 

확실한 타입을 모를 때  general을 사용

type SuperPrint = {
    <TypePlaceholder>(arr: TypePlaceholder[]):void  //general
    }
    
    const superPrint: SuperPrint = (arr) => {
    arr.forEach(i => console.log(i)) //  // 첫번째 조건인 배열을 받아서, 그 배열의 요소를 각각 콘솔로 찍는 작업
}


superPrint([1,2,3,4]) // number 배열
superPrint([true, false, true, true]) // blooean 배열 
superPrint(["1","2","3","4"]) // string 배열
superPrint([1,2,false, true]) //

//
//

 

함수의 call signature을 입력할 때 Placeholder 사용

type SuperPrint = 
    <TypePlaceholder>(arr: TypePlaceholder[])=>TypePlaceholder  //general

 
const superPrint: SuperPrint = (arr) => arr[0] //    // superPrint 배열을 받을거고 superPrit는 그 배열의 첫번째 요소를 리
  


const a =([1,2,3,4]) // number 배열
const b =([true, false, true, true]) // blooean 배열 
const c =(["1","2","3","4"]) // string 배열
const d =([1,2,false, true, "1"]) // number, blooean, string 배열

 

 

제네릭(Generics)

 : placeholder사용해서 작성한 코드의 타입 기준으로 바꿔줌

 : 요구한대로 signatuer를 생성 줄 수 있는 도구

type SuperPrint = <T,M>(a: T[], b:M)=>T  //general이 함수의 두번째 인자를 사용할 것
    //제네릭 처음 인식했을 때와 제네릭의 순서를 기반으로 제네릭의 타입을 알 수 있음
    // T는 함수의 첫번째 (a)파라미터로 배열이 올것임
    // M은 두번째 피라미터로 들어옴 


const superPrint: SuperPrint = (a) => a[0] //    // superPrint 배열을 받을거고 superPrit는 그 배열의 첫번째 요소를 리
  


const a =superPrint([1,2,3,4],x) // number 배열
const b =superPrint([true, false, true, true],1) // blooean 배열 
const c =superPrint(["1","2","3","4"],false) // string 배열
const d =superPrint([1,2,false, true, "1"],[]) // number, blooean, string 배열

 

function superPrint<T>(a:T[]){// arguments는 a, V 배열 받
 return a[0] // a의 첫번쨰 요소를 리턴 
}
const a =superPrint([1,2,3,4]) // number 배열
const b =superPrint([true, false, true, true]) // blooean 배열 
const c =superPrint(["1","2","3","4"]) // string 배열
const d =superPrint([1,2,false, true, "1"]) // number, blooean, string 배열 

//
//

 

제네릭을 사용해 타입을 생성, 타입을 확장 가능, 코드를 저장

type Player<E> = { // 제네릭을 사용해서 다른 타입을 넣고 생성 가능 
    name:string
    extraInfo:E // object,blooean 등 다 될 수 있다.
}
type JihoExtra = {
    favFood:string
}
type JihoPlayer = Player<JihoExtra>

const jiho :JihoPlayer = { //extra안에 object가 들어
    name:"jiho",
    extraInfo:{
        favFood: "icecream"

    }

}
const doongi : Player<null> ={
    name:"doongi",
     extraInfo:null
    
}
type A = Array<number>

let a:A = [1,2]
function printAllNumbers(arr: Array<number>){

}
useState<number>() // useState 제네릭을 받음 number 타입의 useState