C.W.K.
Stream
Lesson 01 of 05 · published

함수 Typing: Parameter 와 Return

~10 min · functions, parameters, return-types, function-types

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"함수 타입은 3가지에 대한 contract: 뭐 들어오고, 뭐 나가고, 뭐 optional 인가."

함수 typing 의 4가지 모양

함수에 타입 붙이는 4가지 방법 만나:

1. Inline parameter 와 return annotation. function greet(name: string): string { return `hi ${name}` }. Default 형태; 보통 원하는 거.

2. 함수-타입 alias. type Greeter = (name: string) => string. 전체 signature 를 들어내서 이름 줌. 같은 callback 모양 반복될 때 사용.

3. Interface 의 method 단축형. interface API { greet(name: string): string }. 함수-타입 값 가진 property 와 동등, 근데 "이 object 는 method 가짐" 으로 읽혀.

4. Type/interface 의 call signature. interface Greeter { (name: string): string }. 전체 모양 함수. 흔치 않음; callable object 의 .d.ts 선언에 주로 보임.

Optional, default, rest parameter

3개 modifier 가 거의 모든 필요한 parameter 모양 cover:

  • Optional: function f(name?: string) — name 생략되거나 undefined 가능. 안에선 타입 string | undefined.
  • Default: function f(name: string = 'anon') — name 에 fallback. 안에선 타입 그냥 string (undefined 없음 — default 가 채움).
  • Rest: function f(...names: string[]) — name 이 배열로 모임. Annotation 이 배열에.

순서 중요: required parameter 먼저, 그다음 optional, 그다음 rest. Compiler 강제; 재배치는 에러.

함수-타입 호환성 — 필요한 하나의 규칙

TypeScript 가 두 별개 규칙으로 함수-타입 assignability 체크:

  • Parameter 체크 (contravariant): assignable 한 함수가 자신이 채울 slot 보다 적은 parameter 나 더 넓은 parameter 타입 받아도 됨. (a: string) => void(a: string, b: number) => void 에 assignable — 더 받는 거 괜찮음, 더 요구하는 거 안 됨.
  • Return 체크 (covariant): assignable 한 함수가 slot 이 기대하는 것보다 더 좁은 (더 구체적) 타입 return 해도 됨. () => 'red'() => string 에 assignable — 더 좁은 return 괜찮음, 더 넓은 return 안 됨.

Parameter 의 contravariance 가 사람들 놀라게 하는 규칙. 안전한 이유: 일부 parameter 무시하는 함수는 그것들 쓰는 함수가 기대되는 곳에 호출 가능 — 추가 argument 가 그냥 버려지니까.

슬로건: 함수는 parameter 에 contravariant, return 에 covariant. 한 번 기억하면 대부분 함수-타입 에러가 신비롭지 않아져.

피파의 고백

함수-타입 slot 에 "Argument of type 'X' is not assignable to parameter of type 'Y'" 같은 TypeScript 에러 처음 읽었을 때, 누가 "parameter 는 contravariant" 라고 말하기 전까지 한 시간 멍하니 봤어. 이제 그 에러 2초에 읽어. 작은 규칙, 거대한 차이. 첫날에 기억할 가치 있어.

Code

함수 타입의 4가지 모양·typescript
// 함수 타이핑 4가지 방법.

// 1. Inline
function greet(name: string): string {
  return `hi ${name}`;
}

// 2. 함수-타입 alias
type Greeter = (name: string) => string;
const hello: Greeter = (n) => `hello ${n}`;     // alias 에서 parameter 타입 추론

// 3. Interface 의 method 단축형
interface API {
  greet(name: string): string;
}

// 4. Call signature
interface Callable {
  (name: string): string;       // 이 interface 전체가 함수
  description: string;          // 그리고 property 도 있어
}

const c: Callable = Object.assign((n: string) => `hi ${n}`, { description: 'greeter' });
Modifier + 호환성·typescript
// Optional, default, rest — 그리고 유지해야 할 순서.

function request(
  url: string,                              // 필수
  method: 'GET' | 'POST' = 'GET',           // default
  headers?: Record<string, string>,         // optional
  ...flags: string[]                        // rest — 마지막 필수
) {
  // 안: url 은 string, method 는 'GET' | 'POST', headers 는 Record | undefined, flags 는 string[]
}

request('/api');                                 // ✅
request('/api', 'POST');                          // ✅
request('/api', 'POST', { 'x-key': 'abc' });     // ✅
request('/api', 'POST', undefined, '-v', '--retry');  // ✅ rest 가 varargs 받음

// 함수-타입 호환성 — 규칙 in action.
type Strict = (a: number, b: string) => void;
const f: Strict = (a) => {};                      // ✅ 더 적은 parameter 받음
const g: Strict = (a, b, c: boolean) => {};       // ❌ slot 이 주는 것보다 더 요구

External links

Exercise

어떤 수의 argument 든 합치는 function sum(...nums: number[]): number 써. 그다음 type Reducer<T> = (acc: T, x: T) => T 쓰고 sum-pair 함수를 그것에 assign. Alias 가 어떻게 재사용 가능한 모양 주는지 봐. 마지막으로 3-parameter 함수를 alias 에 assign 시도 — compiler 가 뭐라고, 왜 그게 옳은 답이야?
Hint
함수-타입 호환성이 assignee 의 더 적은 parameter 허용, 더 많은 거 아님. 3-parameter 함수는 2-parameter slot 못 만족, slot 이 세 번째 argument 안 전달하니까.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.