Menu

TypeScript 선택적 매개변수, 기본값, 나머지 매개변수

TypeScript 매개변수를 ?로 선택적으로 만들거나, 기본값을 주거나, 나머지 매개변수로 인수를 몇 개든 모읍니다. 순서 규칙, 생략과 undefined의 차이, 옵션 객체, 함수 타입의 선택적 매개변수를 다룹니다.

이 페이지에는 실행 가능한 에디터가 있습니다 - 편집하고 실행하면 결과를 바로 볼 수 있습니다.

매개변수 이름 뒤에 ?를 붙이면 선택적 매개변수가 됩니다. 호출하는 쪽은 생략할 수 있고, 함수 안에서 그 타입에는 undefined가 포함됩니다.

TypeScript는 인수 개수를 검사하므로 ?가 없다면 첫 번째 호출은 컴파일 오류입니다: Expected 2 arguments, but got 1.(TS2554).

선택적 매개변수는 undefined일 수 있다

호출하는 쪽이 생략할 수 있으므로 함수 안에서 선택적 매개변수의 타입은 T | undefined입니다. strictNullChecks에서는 T로 쓰기 전에 undefined 경우를 처리해야 합니다.

여기서는 옵셔널 체이닝(?.)과 널 병합(??)을 흔히 씁니다. 대체값이 고정된 값이라면 기본 매개변수가 더 짧습니다.

매개변수 기본값

기본값은 호출하는 쪽에게 매개변수를 선택적으로 만들고, 함수 안에서는 undefined 없는 타입을 줍니다. 타입은 기본값에서 추론되므로 표기가 필요 없는 경우가 많습니다.

호출하는 쪽이 보는 시그니처는 repeat(text: string, times?: number, separator?: string)입니다. 기본값은 JavaScript의 규칙을 따릅니다. 인수가 undefined일 때(생략했든 명시적으로 넘겼든) 적용되고, null일 때는 적용되지 않습니다. 기본값 표현식은 앞의 매개변수를 쓸 수 있습니다: function range(start: number, end = start + 10).

매개변수 순서 규칙

선언컴파일되나?참고
(a: number, b?: number)예선택적 매개변수는 뒤에
(a?: number, b: number)아니요TS1016: A required parameter cannot follow an optional parameter.
(a = 0, b: number)예하지만 기본값을 쓰려면 f(undefined, 5)라고 써야 함
(a: number, ...rest: number[])예나머지 매개변수는 항상 마지막
(a?: number, ...rest: number[])예나머지 앞의 선택적 매개변수는 허용

필수 매개변수 앞에 기본값 매개변수를 두는 것은 합법이지만 어색합니다. 호출하는 쪽에게 그 타입은 number | undefined가 되고, 자리 채우기로 undefined를 쓰는 것을 좋아할 사람은 없습니다. 앞쪽에 유연한 매개변수가 필요하다면 옵션 객체나 함수 오버로딩을 쓰세요.

생략과 undefined

x?: number와 x: number | undefined는 비슷해 보이고 함수 안에서의 타입도 같습니다. 호출하는 쪽에서 다릅니다. 앞의 것은 생략할 수 있고, 뒤의 것은 반드시 넘겨야 합니다.

값이 없어도 되지만 필수인 인수에는 | undefined를 써서 모든 호출자가 그것을 고민하게 하세요. 생략하는 것이 평범한 호출이라면 ?를 쓰세요. (메시지에 정말로 "1 arguments"라고 나오는데, TypeScript의 표현이 그렇습니다.)

나머지 매개변수

나머지 매개변수 ...name: T[]는 인수를 몇 개든 배열로 모읍니다. 반드시 마지막 매개변수여야 합니다.

배열을 고정된 매개변수에 펼치는 것은 더 엄격합니다. 나머지 매개변수는 어떤 number[]를 펼쳐도 받지만, (a: number, b: number)로 선언한 함수는 튜플을 펼친 것만 받습니다. TypeScript가 길이를 알아야 하기 때문입니다.

function point(x: number, y: number) { return { x, y }; }

const list = [3, 4];            // number[]
point(...list);
// error TS2556: A spread argument must either have a tuple type or be passed to a rest parameter.

const pair = [3, 4] as const;   // readonly [3, 4]
point(...pair);                 // fine

나머지 매개변수는 튜플 타입을 가질 수도 있으며, 그러면 각 위치에 타입이 붙습니다: ...args: [name: string, age?: number].

옵션 객체

함수에 선택적 매개변수가 두세 개를 넘으면 호출하는 쪽이 위치를 헷갈리게 됩니다. 기본값이 있는 옵션 객체는 이름이 있고 순서와 무관한 인수를 제공합니다.

끝의 = {}가 객체 전체를 선택적으로 만듭니다. 이것이 없으면 fetchData("/a")는 컴파일 오류(Expected 2 arguments, but got 1., TS2554)이고, 평범한 JavaScript에서는 구조 분해에 읽을 객체가 필요하므로 같은 호출이 런타임에 TypeError를 던집니다.

콜백 타입의 선택적 매개변수

함수 타입에서 ?는 "이 콜백을 호출하는 쪽이 이 인수를 넘기지 않을 수 있다"는 뜻입니다. "콜백이 이 매개변수를 건너뛸 수 있다"는 뜻이 아닙니다. 콜백은 뒤쪽 매개변수를 언제든 무시할 수 있습니다. 그러니 핸들러가 더 적은 인수를 받게 하려고 콜백 매개변수를 선택적으로 표시하지 마세요.

// Too loose: every handler must now cope with index being undefined
type Visit = (item: string, index?: number) => void;

// Right: the caller always passes both; handlers may use only item
type VisitStrict = (item: string, index: number) => void;
const log: VisitStrict = (item) => console.log(item);

자주 묻는 질문

TypeScript에서 매개변수를 선택적으로 만들려면 어떻게 하나요?

이름 뒤에 ?를 붙입니다: function greet(name?: string). 호출하는 쪽은 생략할 수 있고, 함수 안에서 타입은 string | undefined이므로 쓰기 전에 확인합니다. 매개변수에 기본값 name = "there"를 주는 것도 선택적으로 만들고, 함수 안에서 undefined를 없앱니다.

TypeScript에서 선택적 매개변수가 필수 매개변수보다 앞에 올 수 있나요?

?로는 안 됩니다. (a?: number, b: number)는 오류 TS1016, "A required parameter cannot follow an optional parameter."입니다. 기본값이 있는 매개변수는 앞에 올 수 있지만, 그러면 호출하는 쪽이 기본값을 쓰려면 undefined를 명시적으로 넘겨야 하므로 실제로는 선택적 매개변수와 기본값 매개변수를 뒤에 둡니다.

x?: number와 x: number | undefined의 차이는 무엇인가요?

함수 안에서는 둘 다 number | undefined입니다. 차이는 호출하는 곳에 있습니다. x?: number는 인수를 생략할 수 있지만, x: number | undefined는 값이 undefined라도 반드시 넘겨야 합니다. 생략하면 오류 TS2554입니다.

null을 넘기면 기본 매개변수 값이 쓰이나요?

아니요. JavaScript는 인수가 undefined일 때만(생략했거나 명시적으로 넘겼을 때) 기본값을 적용합니다. null은 값이므로 그대로 유지됩니다. 어차피 strictNullChecks에서 TypeScript는 number 매개변수에 null을 거부합니다.

TypeScript에서 배열을 개별 인수로 넘기려면 어떻게 하나요?

펼치세요: fn(...args). 매개변수가 고정된 함수라면 배열이 [number, number] 같은 튜플 타입이거나 as const로 만든 것이어야 합니다. number[]를 펼치면 길이를 모르므로 오류 TS2556입니다. 나머지 매개변수(...values: number[])로 펼치는 것은 항상 됩니다.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기