05. 함수

개발공부·2023년 4월 7일
0

타입스크립트

목록 보기
8/8
post-thumbnail

1. 함수 매개변수

  • 타입스크립트에서 매개변수에 타입을 선언하지 않으면 절대 타입 알 수 없음
    → 매개변수 타입은 무엇이든 될 수 있음
function sing(song: string) { //any에서 string로 타입이 바뀜
    console.log(`Sing: ${song}!`);
}
  • 필수 매개변수

→ 자바스크립트는 인수의 수와 상관없이 함수를 호출할 수 있으나 타입스크립트는 함수에 선언된 모든 매개변수가 필수라고 가정함
→ 함수가 잘못된 수의 인수로 호출되면, 타입스크립트는 타입 오류의 형태로 이의를 제기함

//singTwo 함수는 매개변수가 2개가 아닌 경우 오류남
function singTwo(first: string, second: string) {
	console.log(`${first} and ${second}`);
}

// singTwo('hi'); -> 오류남
singTwo('hi', 'hello'); //ok
  • 매개변수 : 인수로 받을 것으로 예상되는 함수의 선언

  • 선택적 매개변수

→ 자바스크립트는 함수의 매개변수가 제공되지 않으면 함수의 내부 인숫값은 undefined로 기본값이 설정됨

→ 타입스크립트에서는 매개변수가 선택적이라는 뜻에 ?:를 표시

→ [함수 호출]에 선택적 매개변수를 제공할 필요는 없음, | undefined가 유니언 타입으로 추가됨

→ 선택적 매개변수는 마지막 매개변수여야 함

(아래의 announcedSong 매개변수의 위치가 (singer?: string, song: string)이면 오류남)

function announcedSong(song: string, singer?: string) {
    console.log(`Song : ${song}`);

    if(singer) {
        console.log(`Singer: ${singer}`);
    }
}

//모두 다 오류나지 않음
announcedSong('Greenleeves'); 
announcedSong('Greenleeves', undefined);
announcedSong('Chandelier', 'Sia');
  • 기본 매개변수

→ 자바스크립트에서 선택적 매개변수를 선언할 때 =와 같이 포함된 기본값 제공
→ 선택적 매개변수는 기본적으로 값이 제공되기 때문에 해당 타입스크립트 타입에서는 암묵적으로 함수 내부에 | undefined 유니언 타입이 추가됨

function rateSong(song: string, rating = 0) {
    console.log(`${song} gets ${rating}/5 stars!`);
}

rateSong('Photograph');
rateSong('Set fire to the Rain', 5);
rateSong('Set fire to the Rain', undefined);

//오류
//rateSong('At Last!', '100'); //number아닌 string값
  • 나머지 매개변수

→ 자바스크립트 일부 함수는 임의의 수의 인수로 호출할 수 있도록 만들어짐
… 연산자는 함수 선언의 마지막 매개변수에 위치, 해당 매개변수에서 시작해 함수에 전달된 나머지 인수가 모두 단일 배열에 저장되어야 함
→ 다만 타입스크립트는 인수 배열을 나타내기 위해 []이 추가됨

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

singAllTheSongs('Alicia Keys');
singAllTheSongs('Lady Gaga', 'Bad Romance', 'Just Dance', 'Poker Face');

// singAllTheSongs('Ella Fitzgerald', 2000);
// Argument of type 'number' is not assignable to parameter of type 'string'

2. 반환 타입

  • 타입스크립트는 함수가 반환할 수 있는 가능한 모든 값을 이해하면 함수가 반환하는 타입을 알 수 있음
//타입 : (songs: string[]) => number
function singSongs(songs: string[]) {
    for(const song of songs) {
        console.log(`${song}`);
    }
    return songs.length;
}
// (songs: string[], index: number): string | undefined
function getSongAt(songs: string[], index: number) {
    return index < songs.length
        ? songs[index]
        : undefined
}
  • 명시적 반환 타입

→ 가능한 반환값이 많은 함수가 항상 동일한 타입의 값을 반환하도록 강제함
→ 타입스크립트는 재귀 함수의 반환 타입을 통해 타입을 유추하는 것을 거부함
→ 수백 개 이상의 타입스크립트 파일이 있는 매우 큰 프로젝트에서 타입스크립트 타입 검사 속도를 높일 수 있음

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

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

3. 함수 타입

  • 자바스크립트에서 함수를 값으로 전달 가능
    → 함수를 가지기 위한 매개변수 또는 변수의 타입을 선언하는 방법 필요함
let nothingInGivesString: () => string; //매개변수가 없고 string 타입 반환
let inputAndOutput: (songs: string[], count?: number) => number;
//string 매개변수와 count 선택적 매개변수 및 number값 반환
  • 콜백 매배견수(함수로 호출되는 매개변수)를 설명하는데 함수 타입이 자주 사용됨

→ runOnSongs 함수는 getSongAt 매개변수 타입을 index: number로 받고 string을 반환하는 함수로 선언
→ getSongAt을 전달하면 타입 일치
→ logSong은 매개변수로 number 대신 string을 사용하므로 반환값 가져오지 못함

const songs = ['Juice', 'Shake it off', 'What is up'];

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 logSong(song: string) {
    return `${song}`;
}

// runOnSongs(logSong);

//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'
  • 함수 타입 괄호

→ 함수 타입은 다른 타입이 사용되는 모든 곳에 배치할 수 있음(유니언 타입 포함)
→ 유니언 타입의 애너테이션에서 함수 반환 위치를 나타내거나 유니언 타입을 감싸는 부분을 표시할 때 괄호 사용

//타입은 string | undefined 유니언을 반환하는 함수
let returnStringOrUndefined: () => string | undefined;

//타입은 undefined나 string을 반환하는 함수
let maybeReturnString: (() => string) | undefined;
  • 매개변수 타입 추론
    → 선언된 타입의 위치에 제공된 함수의 매개변수 타입을 유추할 수 있음
let singer: (song: string) => string;

singer = function(song) {
	//song: string 타입
	return `Singing: ${song.toUpperCase()}`
}
const songs = ['Call me', 'Jolene', 'The Chain'];

songs.forEach((song, index) => {
	console.log(`${song} is at index ${index}`);
})
  • 함수 타입 별칭

→ 반복적으로 작성하는 매개변수와 반환 타입을 갖는 코드 공간을 많이 절약 가능

type StringToNumber = (input: string) => number;

let stringToNumber: StringToNumber;

stringToNumber = (input) => input.length;

//오류
// stringToNumber = (input) => input.toUpperCase();

type NumberToString = (input: number) => string;

function useNumberToString(numberToString: NumberToString) {
    console.log(`The string is ${numberToString(1234)}`);
} 

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

//오류
// useNumberToString((input) => input * 2);

4. 그 외 반환 타입

  • void 반환 타입

→ 어떤 값도 반환하지 않음
→ 반환 값이 없는 함수의 반환 타입을 확인할 수 있음

function logSong(song: string | undefined): void {
    if(!song) {
        return;
    }
    console.log(`${song}`);
    return true;
    //Type 'boolean' is not assignable to type 'void'
}
  • songLogger는 song: string을 받고 값을 반환하지 않는 함수
let songLogger: (song: string) => void;

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

songLogger("Heart of Glass");
  • void 특성

→ 자바스크립트는 실제값이 반환되지 않으면 기본으로 모두 undefined를 반환하나 void는 undefined와는 다름
→ 함수 반환 타입이 무시된다는 것을 의미, undefined는 반환되는 리터럴 값
→ undefined를 포함하는 대신 void 타입의 값을 할당하려고 하면 타입 오류

function returnsVoid() {
    return;
}

let lazyValue: string | undefined;

//오류
lazyValue = returnsVoid();
//Type 'void' is not assignable to type 'string | undefined

→ 자바스크립트가 아닌 함수의 반환 타입을 선언하는데 유용
→ 함수의 반환값이 자체적으로 반환될 수 있는 값이 아니고 사용하기 위한 것도 아니라는 표시 기억해야 함

const records: string[] = [];

function saveRecords(newRecords: string[]) {
	newRecords.forEach((record => records.push(record));
}

saveRecords(['21', 'Come on Over', 'The BodyGuard']);
  • never 반환타입

→ 값을 반환하지 않을 뿐만 아니라 반환할 생각도 없음
→ 의도적으로 항상 오류 발생시키거나 무한루프 생성

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

function workWithUnsafeParam(param: unknown) {
	if(typeof param != 'string') {
		fail(`param should be a string, not ${typeof param}`);
	}
	//param 타입 : string
	param.toUpperCase();
}

5. 함수 오버로드

  • 오버로드 시그니처 : 일부 자바스크립트 함수는 선택적 매개변수와 나머지 매개변수만으로 표현할 수 없는 매우 다른 매개변수들로 호출될 수 있음

→ 하나의 최종 구현 시그니처와 그 함수의 본문 앞에 서로 다른 버전의 함수 이름, 매개변수, 반환 타입을 여러 번 선언

→ 오버로드된 함수 호출에 대해 구문오류 생성할 지 여부 결정하는 경우

⇒ 타입스크립트는 함수의 오버로드 시그니처만 확인

⇒ 구현 시그니처는 함수의 내부 로직에서만 사용

  • createDate 함수는 1개의 timestamp 매개변수 또는 3개의 매개변수(month, day, year)를 사용해 호출

→ 허용된 수의 인수를 사용해 호출할 수 있으나 2개의 인수를 사용해 호출하면 2개의 인수를 허용하는 오버로드 시그니처가 없기에 타입오류 발생

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

createDate(55436000);
createDate(7, 27, 1987);

//오류
createDate(4, 1);
// No overload expects 2 arguments, but overloads do exist that expect either 1 or 3 arguments.
  • 호출 시그니처 호환성

→ 오버로드된 함수의 구현에 사용되는 구현 시그니처는 매개변수 타입과 반환 타입에 사용하는 것과 동일함
→ 함수 오버로드 시그니처에 있는 반환 타입과 각 매개변수는 구현 시그니처에 있는 동일한 인덱스의 매개변수에 할당할 수 있어야 함
→ 구현 시그니처는 모든 오버로드 시그니처와 호환되어야 함

  • format 함수 구현 시그니처는 첫 번째 매개변수 string
    → 처음 두 개의 오버로드 시그니처는 string 타입과 호환되나 세 번째 오버로드 시그니처의 () ⇒ string 타입과는 호환되지 않음
function format(data: string): string;
function format(data: string, needle: string, haystack: string): string;

// 오류
function format(getData: () => string): string;

//This overload signature is not compatible with its implementation signature

function format(data: string, needle?: string, haystack?: string) {
    return needle && haystack ? data.replace(needle, haystack : data);
}
profile
개발 블로그, 티스토리(https://ba-gotocode131.tistory.com/)로 갈아탐

0개의 댓글