자바스크립트 프로그램에서 가장 핵심적인 역할을 차지하는 함수 타입이 타입스크립트에서 어떻게 표현되는 지 다룬다.
함수의 타입을 결정하기 위해서는 다음 두 가지 정보가 필요하다.
1. 매개변수(parameter)의 타입
2. 반환값(return value)의 타입(반환 타입)
매개 변수의 경우, 변수의 타입을 표기할 때와 마찬가지로 매개변수 뒤에 콜론(:)을 붙이고 타입을 적는다. (param1: number)
반환 타입은 매개변수 목록을 닫는괄호())와 함수 본문을 여는 대괄호({)사이에 콜론을 붙이고 표기한다. function (): number {...}
예를 들어 두 숫자를 받아 그 합을 반환하는 함수는 다음과 같이 타입을 표기한다.
function sum(a: number, b:number): number {
return (a+b);
}
만약 함수가 아무런 값도 반환하지 않고 종료된다면 반환 타입으로 void를 사용한다.
function logGreetings(name: string): void {
console.log(`Hello, ${name}!`);
}
void 반환 타입을 갖는 함수가 undefined 나 null 이외의 값을 반환하면 타입 에러가 발생한다. void가 아닌 반환 타입을 갖는 함수가 아무 값도 반환하지 않는 경우도 마찬가지다.
function notReallyVoid(): void {
return 1;
}
// error TS2322: Type '1' is not assignable to type 'void'.
function actuallyVoid(): number { }
// error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
함수 타입의 값에 타입 표기를 붙이기 위해서는 화살표 함수 정의 문법과 비슷한 문법을 사용한다.
(...매개변수 나열) => 반환 타입
매개변수가 없는 함수의 경우 매개변수를 생략해 아래와 같이 적는다
() => 반환 타입
const yetAnotherSum: (a: number, b: number) => number = sum;
const onePlusOne: () => number = () =>2;
const arrowSum: (a: number, b:number) => number = (a, b) => (a + b);
ES6와 마찬가지로, 타입스크립트에서도 기본 매개 변수 문법을 사용할 수 있다. 이때 기본 값은
매개변수명: 타입 = 기본값
function greetings(name: string = 'stranger'): void {
console.log(`Hello, ${name}`);
}
greetings('Heejong'); // Hello, Heejong!
greetings();// Hello, stranger!
많은 프로그래밍 언어는 함수 정의에 명시된 매개 변수의 수보다 많거나 적은 수의 인자가 들어온 경우 에러를 뱉는다. 한편, 자바스크립트는 더 들어온 인자는 버리고, 덜 들어온 인자는 undefined가 들어온 것과 동일하게 취급한 후 어떻게든 함수를 실행하려 시도한다.
이런 언어의 특성 및 기존 사용 예를 포용하면서 타입 안정성을 확보하기 위해 타입스크립트는 선택 매개변수를 지원한다. 함수의 매개변수 이름 뒤에 물음표 기호를 붙여 해당 매개변수가 생략될 수 있음을 명시한다.
예를들어, optional?: number로 선언된 선택 매개변수 optional를 함수 본문에서 number 타입 값으로 사용하려면 해당 값이 undefined가 아닌지를 먼저 검사해야 한다.
function fetchVideo(url: string, subtitleLanguage?: string) {
const option = {url};
if (subtitleLanguage) {
option.subtitleLanguage = true;
}
}
fetchVideo('https://example.com', 'ko'); // okay
fetchVideo('https://example.com'); // also okay
이 때 매개변수 정의 순서에서 선택 매개변수 이후에 필수 매개변수를 두는 것은 허용되지 않는다.
이러한 제약이 존재하는 이유는 만약 필수 매개변수가 선택 매개 변수 뒤에 있을시, 인자가 어떤 매개변수의 값인지 구분할 수 없기 때문이다.
자바스크립트에서는 한 함수가 여러 쌍의 매개변수-반환 타입 쌍을 갖는 경우가 매우 흔하다. 이런 함수의 타입을 정의할 수 있게 하고자 타입스크립트는 함수 오버로딩을 지원한다. 타입스크립트의 함수 오버로딩은 다음과 같은 특징을 갖는다.
즉, 오버로딩을 통해서 여러 형태의 함수 타입을 정의할 수 있지만, 실제 구현은 한 번만 가능하므로 여러 경우에 대한 분기는 함수 본문내에서 이루어져야 한다.
function doubleString(str: string): string {
return `${str}${str}`;
}
function doubleNumber(num: number): number {
return (num * 2);
}
function doubleBooleanArray(arr: boolean[]): boolean[] {
return arr.concat(arr);
}
위 세 함수를 함수 오버로딩을 사용해서 하나의 double이라는 함수로 합쳐보자.
function double(arg) {
if (typeof arg === 'string') {
return `${str}${str}`;
} else if (typeof arg === 'number') {
return arg * 2;
} else if (Array.isArray(arr)) {
return arg.concat(arg);
}
}
이렇게 오버로딩을 통해 정의된 double 함수는 호출되는 인자의 타입에 따라 반환타입이 달라진다.
자바스크립트 함수 내부에서의 this 값은 함수가 정의되는 시점이 아닌 실행되는 시점에 결정된다. 이런 특성은 함수 내부에서 this의 타입을 추론하는 일을 매우 어렵게 만든다. 타입스크립트는 이런 어려움을 해결하기 위해 함수 내에서의 this 타입을 명시할 수 있는 수단을 제공한다.
함수의 this 타입을 명시하기 위해선 함수의 타입 시그니쳐에서 매개변수 가장 앞에 this를 추가해야 한다. 이 때 this 타입은 타입 시스템을 위해서만 존재하는 일종의 가짜 타입이다. 즉, this 매개변수를 추가한다고 해도 함수가 받는 인자수와 같은 실제 동작은 변하지 않는다.
출처 : https://ahnheejong.gitbook.io/ts-for-jsdev/03-basic-grammar/function