[하루 30분 러닝 타입스크립트] 함수

✨함수 매개변수

필수 매개변수

function singTwo(first: string, second: string){
    console.log(`${first} ${second}`)
}
// 이 함수의 매개변수는 2개 이다.
// 1개 혹은 3개의 매개변수는 허용하지 않는다.

singTwo("a") // ERROR Expected 2 arguments, but got 1.
singTwo("a","b") // OK
singTwo("a","b","c") // ERROR Expected 2 arguments, but got 3.

선택적 매개변수

타입 애너테이션의 : 앞에 ? 를 추가해 선택적으로 사용할 수 있습니다.

function singTwo(first: string, second?: string){
    console.log(`${first} ${second}`)
}
// 이 함수의 매개변수는 1개 혹은 2개 이다.

singTwo("a") // OK
singTwo("a","b") // OK
singTwo("a",undefined) // OK
singTwo("a","b","c") // ERROR Expected 1-2 arguments, but got 3.
function singTwo(first: string, second?: string){
    console.log(`${first} ${second}`)
}
// 이는 다음과 같습니다.
function singTwo(first: string, second: string | undefined){
    console.log(`${first} ${second}`)
}

기본 매개변수

자바스크립트에서 = 를 이용해 기본값을 제공할 수 있습니다.

이 경우에도 undefined를 허용합니다. 하지만 유추 된 타입과 다른 타입은 허용하지 않습니다.

function ratingSong(song: string, rating = 0){
    console.log(`${song} get ${rating}!`)
}

ratingSong("Photograph") // OK
ratingSong("Photograph", 1) // OK
ratingSong("Photograph", undefined) // OK

ratingSong("Photograph", "100") 
// ERROR Argument of type 'string' is not assignable to parameter of type 'number'.

나머지 매개변수

… 스프레드 구문을 이용하여 나머지 인수의 타입을 사용할 수 있습니다.

function singAllTheSongs(singer: string, ...songs: string[]){
    for(const song of songs){
        console.log(`${song} by ${singer}`)
    }
}

singAllTheSongs("Alica Keys") // OK
singAllTheSongs("Alica Keys", "A", "B", "C") // OK

singAllTheSongs("Alica Keys", 2000) 
// ERROR Argument of type 'number' is not assignable to parameter of type 'string'.

✨반환 타입

타입 스크립트는 지각적(perceptive) 입니다. 타입을 추론할 수 있다는 것입니다.

반환 타입 역시 모든 반환 타입의 조합으로 유추합니다.

명시적 반환 타입

다음과 같은 특징을 가집니다.

  1. 반환 값이 많은 함수가 항상 동일한 타입의 값을 반환하도록 강제합니다.
  2. 타입스크립트는 재귀 함수의 반환 타입을 유추하는 것은 거부합니다.
  3. 타입스크립트 타입 검사 속도를 높힐 수 있습니다.

반환 타입은 ) 뒤에 : 키워드를 통해 표현합니다.

function singSongsRecursive(songs: string[], count = 0): number{
    return songs.length ? singSongsRecursive(songs.slice(1), count + 1) : count
}
// const singSongsRecursive: (songs: string[], count?: number) => number

화살표 함수는 다음과 같습니다.

const singSongsRecursive = (songs: string[], count = 0): number => 
    songs.length ? singSongsRecursive(songs.slice(1), count + 1) : count

✨함수 타입

자바스크립트는 함수를 값으로 전달할 수 있습니다.

const songs = ["A", "B", "C"];

function runOnSongs(getSongAt : (index: number) => string){
    for(let i = 0; i < songs.length; i+=1){
        console.log(getSongAt(i))
    }
}

function getSongAt(index: number){
    return `${songs[index]}`
}
runOnSongs(getSongAt) // OK

function logSongs(song: string){
    return `${song}`
}
runOnSongs(logSongs)
/* ERROR 
Argument of type '(song: string) => string' is not assignable to parameter of type '(index: number) => string'.
  Types of parameters 'song' and 'index' are incompatible.
    Type 'number' is not assignable to type 'string'.
*/

함수 타입 괄호

let returnStringOrUndefind : () => string | undefined

let maybeRetrunsString : ( ()=>string ) | undefined

매개변수 타입 추론

함수를 매개변수로 갖는 함수에 인수로 전달된 함수는 해당 매개변수 타입도 잘 유추할 수 있습니다.

const songs = ["A", "B", "C"]

songs.forEach((song, index) => {
    console.log(`${song} is at index ${index}`)
}) // song: string, index: number 으로 유추

✨그 외 반환 타입

void 반환 타입

어떤 값도 반환하지 않는 타입을 의미합니다,

function logSong(song: string | undefined): void {
    if(!song) return // OK

    console.log(`${song}`);

    return true // ERROR Type 'boolean' is not assignable to type 'void'.
}

이는 undefined와 다릅니다. 자바스크립트 함수는 값이 반환되지 않으면 undefined 를 반환하지만, void 와 구분하여 사용하여야 합니다.

  1. void는 아무것도 반환하지 않을 때 사용 (rerturn)
  2. undefined는 반환 값이 undefined 일 때 사용. (return undefined)

never 반환 타입

일부 함수는 값을 반환할 뿐만 아니라 반환할 생각도 전혀 없습니다.

function fail(message: string): never {
	throw new Error(`Invariant failure: ${message}`)
}

✨함수 오버로드

일부 함수들은 선택적 매개변수와 나머지 매개변수 만으로 표현하기 힘든 매개변수들이 호출될 수 있습니다. 이는 오버로드 시그니처라 불리는 타입스크립트 구문으로 표현할 수 있고, 최종적으로 구현 시그니처로 표현할 수 있습니다.

function createDate(timestamp: number): Date; // 오버로드 시그니처
function createDate(month: number, day: number, year: number): Date; // 오버로드 시그니처
 // 구현 시그니처
function createDate(monthOrtimestamp: number, day?: number, year?: number) {
    return day === undefined || year === undefined
        ? new Date(monthOrtimestamp)
        : new Date(year, monthOrtimestamp, day)
}

호출 시그니처 호환성

구현 시그니처는 모든 오버로드 시그니처와 호환되어야 합니다.

function createDate(timestamp: number): Date; 
function createDate(month: number, day: number, year: number): Date; 

function createDate(month: () => number, day:number, year: number ): Date;
// ERROR This overload signature is not compatible with its implementation signature.

function createDate(monthOrtimestamp: number, day?: number, year?: number) {
    return day === undefined || year === undefined
        ? new Date(monthOrtimestamp)
        : new Date(year, monthOrtimestamp, day)
}