목차
TypeScript 함수: 인자와 반환값의 계약
자바스크립트 함수는 호출 시 인자가 부족하면 해당 매개변수가 undefined가 된다. TypeScript는 코드를 검사할 때 선언된 필수 인자의 개수를 확인한다. 타입 오류가 발생해도 이미 배포된 JavaScript의 런타임 동작을 바꾸지는 않는다. 외부 입력이 실제로 문자열인지 확인해야 한다면 별도 런타임 검증이 필요하다.
function sing(song: string): string {
return `Singing: ${song}!`;
}
console.log(sing("노래")); // Singing: 노래!
// sing(123); // 컴파일 오류: number는 string이 아님
// sing(); // 컴파일 오류: 필수 인자가 없음
(song: string)은 인자의 타입, : string은 반환 타입이다. 반환 타입을 생략해도 본문에서 추론할 수 있지만 공개 API에서는 명시하면 계약을 읽기 쉽다. 함수가 아무것도 반환하지 않으면 void, 절대 정상 반환하지 않으면 never를 사용할 수 있다.
선택적 인자와 기본값
function formatName(first: string, last?: string): string {
return last === undefined ? first : `${first} ${last}`;
}
formatName("Kim"); // "Kim"
formatName("Kim", "Min"); // "Kim Min"
function greet(name: string, prefix = "안녕하세요"): string {
return `${prefix}, ${name}`;
}
greet("Kim"); // "안녕하세요, Kim"
greet("Kim", "반갑습니다"); // "반갑습니다, Kim"
last?: string은 함수 안에서 string | undefined이므로 사용 전에 확인한다. 선택적 인자는 필수 인자 뒤에 둔다. 기본값을 지정한 prefix는 호출자가 생략하거나 undefined를 넘길 때 기본값이 들어가며 함수 본문에서는 문자열로 다룰 수 있다. null은 기본값을 작동시키지 않으므로 둘을 같은 의미로 보지 않는다.
나머지 인자와 함수 타입
function joinWords(first: string, ...rest: string[]): string {
return [first, ...rest].join(" ");
}
joinWords("A", "B", "C"); // "A B C"
type Lookup = (index: number) => string;
const songs = ["Juice", "Shake It Off"];
const getSong: Lookup = index => songs[index] ?? "알 수 없음";
function printSongs(lookup: Lookup, count: number): void {
for (let i = 0; i < count; i++) console.log(lookup(i));
}
printSongs(getSong, songs.length);
...rest는 전달한 나머지 인자를 배열로 받는다. Lookup은 숫자를 받아 문자열을 돌려주는 함수의 모양이다. 원래 예제의 배열 인덱스 접근은 범위를 벗어나면 undefined가 될 수 있으므로 ??로 기본값을 정했다. 입력 범위를 엄격하게 제한해야 한다면 기본값보다 예외나 결과 타입으로 오류를 알린다.
함수를 저장하는 타입 () => string[]과 함수들의 배열 타입 (() => string)[]은 다르다. 전자는 함수 하나가 문자열 배열을 반환, 후자는 각각 문자열 하나를 반환하는 함수 여러 개다. 괄호 위치가 의미를 바꾼다.
const allSongs: () => string[] = () => ["A", "B"];
const producers: (() => string)[] = [() => "A", () => "B"];
유니언 배열과 튜플
let oneStringOrNumberArray: string | number[] = "ready";
oneStringOrNumberArray = [1, 2];
let mixedItems: (string | number)[] = ["A", 2];
const yearAndName: [number, string] = [530, "Tomyris"];
const [year, warriorName] = yearAndName;
string | number[]는 문자열 하나 또는 숫자 배열이고 (string | number)[]는 각 원소가 문자열이나 숫자인 배열이다. 튜플은 인덱스별 타입과 필요한 원소 수를 지정한다. API가 두 값을 순서로 반환하면 편리하지만 값의 의미가 모호하다면 { year, name } 객체가 읽기 쉽다.