관리 메뉴

꿈꾸는 개발자

5장 함수 본문

Learning Typescript

5장 함수

rickysin 2023. 3. 3. 23:16

5.1 함수 매개변수


function sing(song){}
  • 위와 같이 매개변수의 타입을 명시하지 않으면 TS에선 any로 간주함
  • 변수와 마찬가지로 매개변수에도 타입 애너테이션을 선언 가능!
function sing(song:string){
    console.log(`Singing ${song}`)
}

5.1.1 필수 매개변수


  • TS에선 함수에 선언된 모든 매개변수가 필수라고 가정함, 인수의 수가 잘못된 상태로 함수가 호출되면 타입 오류! ⇒ 타입 안정성을 강화하는 데 도움을 줌

5.1.2 선택적 매개변수


  • 선택적 매개변수에는 항상 | undefined가 유니언 타입으로 추가돼 있다.
  • 따라서, JS처럼 값을 할당하지 않았을 때 undefined이 나오도록 하고 싶으면 밑과 같이
function announceSong(song:string, singer?:string){ // string | undefined이란 의미!
 console.log(`Song: ${song}`);

 if(singer){
    console.log(`Singer: ${singer}`);
    }
}
announceSong("Green"); //ok;
announceSong("green", undefined); //ok;
announceSong("gaga","sasa");//ok
  • 선택적 매개변수는 | undefined을 포함하는 유니언 타입과 엄연히 다르다. ?으로 표시되지 않은 매개변수는 undefined으로 인수를 주더라도 무조건 값을 주어야 함!
  • 함수에서 사용되는 선택적 매개변수는 무조건 마지막 매개변수여야 한다⇒ 아닐 경우 구문 오류 발생!

5.1.3 기본 매개변수


  • TS에서 함수의 매개변수에 대해 인수 누락+ undefined 인수를 사용해 호출 하는 것을 허용함(기본값을 제공했다는 전제 아닐시 에러발생함!)
function rateSong(song:string, rating=0){ //자동으로 타입이 지정되기 때문에!
    console.log(`${song} gets ${rating}/5 stars!`);
}
rateSong("Photograph");//ok
rateSong("Set Fire",5); //ok
rateSong("SEt Fire to the Rain", undefined);//ok
rateSong("At Last!","100"); //error Argument of type "100"
  • rateSong()함수에서 rating은 number타입으로 유추됨 ⇒ 선택적으로 number | undefined으로 간주된다.

5.1.4 나머지 매개변수


  • TS에선 나머지 매개변수를의 타입을 일반 매개변수와 유사하게 선언할 수 있다. ⇒단 인수 배열을 나타내기 위해 [] 구문이 추가됨
function singAllTheSong(singer:string, ...songs:string[]){ //string 타입의 배열을  의미함
    for(const song of songs){
        console.log(`${song}, by ${singer}`);
    }
}

singAllTheSong("Alalal"); //ok
singAllTheSong("a","b","C","d")//ok 
singAllTheSong("a",100); //type error occurs

5.2 변환 타입


//타입 (songs:string[])=>number을 반환
function sing(songs:string[]){
    for(const song of songs){
        console.log(`${song}`);
    }
    return songs.length;
}
//배열의 길이를 number 타입으로 반환한다.
  • 여러 개의 반환문을 포함하면 ⇒ TS 반환 타입 을 가능한 모든 타입 조합으로 유추!
function getSong(songs:string[],index:number){
    return index<songs.length?songs[index]:undefined;
}
  • 위코드의 경우 반환 값은 string | undefined이기 떄문에 둘 다 유추를 함!

5.2.1 명시적 반환 타입


  • 함수의 반환 타입을 명시하지 않는 것이 좋음 ⇒ 하지만 이것이 유용할 경우가 종종 있음
    • 반환값이 많은 함수의 경우 동일한 타입의 값을 반환하도록 강제
    • TS는 재귀함수의 반환 타입을 통해 타입 유추하는 것을 거부함
    • TS파일이 무수히 많을 경우 타입 검사 속도를 높일 수 있음
function a (songs:string[], count=0):number{
    return songs.length? singSong(songs.slice(1),count+1):count;
}

const b =(songs:string[], count=0):number=>{
    return 1; 
}
  • 일반 함수 선언과 화살표 함수에서 반환 타입 애너테이션을 하는 법
function example1(a:string):number| undefined{
    if(a){
        return 1;
    }else{
        return undefined;
    }
}
function example2(a:string):number| undefined{
    if(a){
        return "hello"; //string 반환 불가 에러 발생!
    }else{
        return undefined;
    }
}
  • 반환할 수 없는 타입을 반환할 경우 에러가 발생함

5.3 함수 타입


  • 함수 타입은 콜백 매개변수를 설명할 때 자주 사용됨 (JS에서 함수는 일급 객체임을 명심)
const songs=["a","b","c","d"];

//getsont은 매개변수 타입은(index:number)이고 string을 반환하는 함수로 선언함!
function runOn(getSont:(index:number)=>string){
    for(let i=0;i<songs.length; i++){
        console.log(getSont(i));
    }
}   

function getsont(index:number){
    return `${songs[index]}`;
}

runOn(getsont);//ok 

function logSong(song:string){
    return `${song}`;
}
runOn(logSong);//매개변수의 타입이 달라서 안된다고 나옴

  • 각 들여쓰기에 따른 오류 표시
  1. 일치하지 않는 부분을 지적
  2. 두 함수의 타입을 출력
  3. 일치하지 않는 부분에 대한 정확한 할당 가능성 오류 출력!

5.3.1 함수 타입 괄호


  • 함수 타입에서도 유니언 타입 사용 가능!
//string | undefined 유니언 타입을 반환하는 함수
let test:()=> string | undefined;
  • 타입은 undefined나 string 둘 중 하나를 반환하는 함수
//타입은 undefine나 string을 반환하는 함수
let testb:(()=>string)|undefined;

5.3.2 매개변수 타입 추론


//singer는 string 타입의 매개변수를 갖는 함수이기에 => song매개변수는 string으로 예측됨
let singer:(song:string)=>string; 
singer=function(song){
    return`Singing: ${song.toUpperCase()}`;
}
  • TS는 선언된 타입의 위치에 제공되는 함수의 매개변수 타입 유추 가능!
const songs=['a','b','c'];
//각각으로 유추된다!
//song:string
//index:number;
songs.forEach((el,idx)=>{
    console.log(`${el} is at index:${idx}`);
});
  • 매번 타입을 명시할 필요가 없다는 의미!?

5.3.3 함수 타입 별칭


type StringtoNumber=(input:string)=>number; //함수의 타입 별칭

let stringToNumber:StringtoNumber; //해당 변수에 타입 별칭 명시

stringToNumber=(input)=>input.length; //return타입이 number이라 가능

stringToNumber=(input)=>input.toUpperCase();// return type은 number이다!
  • 매개변수에도 사용 가능(콜백 함수를 의미함)
type StringtoNumber=(input:number)=>string; //함수의 타입 별칭

function useNumberToString(numberTostring:StringtoNumber){
    console.log(`The string is ${numberTostring(1234)}`);
}//매개변수 타입 별칭으로 사용 가능

useNumberToString((input)=>`${input}! asd!`);

useNumberToString((input)=>input*2);//return type이 string이라 에러 발생
  • 함수를 작성할 때 타입 별칭은 유용하게 사용됨 ⇒ 매개변수와 반환 타입 코드 공간 확보 가능!

5.4 그 외 반환 타입


  • void와 never에 대해 다룬다

5.4.1 void 반환 타입


  • void를 통해 반환값이 없는 함수 반환 타입을 확인 가능
function logSong(song:string| undefined):void{
    if(!song){
        return; //ok 아무것도 반환하지 않음(void)
    }

    return true; //에러 발생

}
let songLogger:(song:string)=>void 

songLogger=(songs)=>{
    console.log(`${songs}`);
}

songLogger("asdfadfs"); //ok
  • JS에선 반환값이 없으면 암묵적으로 undefined을 반환한다.
  • void ≠ undefined
  • void를 반환하도록 선언된 타입 위치에 전달된 함수가 반환된 모든 값을 무시할 때 유용함 (forEach는 void를 반환하는 콜백을 받는다)
    • record ⇒ records.puhs(record)와 같은 콜백을 받더라도 허용됨!

5.4.2 never 반환 타입


  • never 반환 함수는 항상 오류를 발생시킴/무한 루프를 실행하는 함수
  • TS 제어 흐름 분석을 도와준다! (좁히기 위해서 사용하기도 함)
function fail(message:string):never{
    throw new Error(`${message}`);
}

function workWithUnsafeParam(param:unknown){
    if(typeof param!=="string"){
        fail("param should be string")
    }
    param.toUpperCase();
}
  • never≠void

5.5 함수 오버로드


  • 오버로드 시그니처(overlad signature): 선택적 매개변수/나머지 매개변수로 표현할 수 없는 매개변수들로 호출되는 함수 ⇒ 하나의 최종 구현 시그니처에 서로 다른 버전의 함수 이름, 매개변수, 반환 타입을 여러 번 선언함!

 

 


Reference

  • 조시 골드버그, 러닝 타입스크립트, 고승원 옮김, 2023