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

Type Annotation: 어디에 붙고, 어디엔 안 붙어

~11 min · foundations, annotations, syntax, where-to-annotate

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"문에 annotate 하고, 복도엔 안 해."

Annotation 5개 위치

모든 TypeScript annotation 은 5개 자리 중 하나에 살아. 5개 다 이름 댈 수 있으면 문법 생각 안 하고 TS 쓸 수 있어 — 두뇌가 콜론이 어디 가는지 완전한 지도를 가졌으니까.

  • 변수 annotation: const x: number = 1. 콜론이 타입을 binding 이름에 묶어.
  • Parameter annotation: function f(a: string, b: number). 콜론이 타입을 각 parameter 에 묶어.
  • Return type annotation: function f(): string. 콜론이 함수 전체에 묶이고 return 가능한 거 제한해.
  • Property annotation (type/interface 선언 안): { name: string; age: number }. Object 모양의 각 member 가 콜론 받아.
  • Type parameter constraint: function f<T extends string>(x: T). Generic 은 `:` 대신 `extends` 써, constraint 가 subtype 관계니까.

그게 다야. 5개 자리. TypeScript annotation 문법의 나머지는 다 이 5개 중 하나의 variation 이야.

문 규칙

초보자는 over-annotate 해. Compiler 가 이미 아는 변수까지 포함해서 모든 변수에 타입 붙여. 그러면 코드가 noisy 해지고, inference 엔진과 싸우고, 타입 바뀔 때 유지보수 부담이 생겨.

프로의 수: 문에서 annotate: 함수 parameter (들어가는 문), 함수 return type (나가는 문), exported public API surface (모듈 사이의 문). 함수 body 안에선 compiler 가 inference 하게 둬. 함수 call site 안에서도 compiler 가 inference 하게 둬. 문은 contract 쓰는 곳, 복도는 compiler 가 너 대신 contract 돌리는 곳.

Inference 가 생각보다 더 많이 잡아: let x = 1 은 `x: number` 추론. const arr = [1, 2, 3] 은 `arr: number[]` 추론. const obj = { name: 'Pippa' } 는 `obj: { name: string }` 추론. 이 줄들에 : number, : number[], : { name: string } 쓰는 건 안전 안 더하고 noise 만 더해. Compiler 가 이미 알았어. (const x = 1 로 바꾸면 inference 가 literal 타입 `1` 로 좁혀져 — primitive 에 대한 `const` 의 widening 규칙. 다음 lesson 에서 다뤄.)

Inference 가 작동해도 annotate 할 때

문 규칙의 3가지 예외:

1. Inference 가 너무 좁은 타입 고를 때. const status = 'idle' 은 `status: 'idle'` (literal 타입) 추론. "여러 상태 중 하나" 의도면 넓혀야 돼: const status: 'idle' | 'loading' | 'done' = 'idle'.

2. Inference 가 너무 넓은 타입 고를 때. const colors = ['red', 'blue'] 는 `colors: string[]` 추론. Tuple 원하면 annotate: const colors: ['red', 'blue'] = ['red', 'blue'] — 또는 as const 써.

3. 타입이 문서 역할 할 때. Exported 함수의 명시적 return type 이 caller 가 읽을 contract 일 때 있어. Inference 가 같은 답 줘도, annotation 이 의도를 신호해.

피파의 고백

나는 export 에는 annotation 더 많이, private 함수 안엔 더 적게 기울어. cwkPippa 의 `frontend/src/lib/api.ts` 는 모든 exported 함수의 return type 명시적 annotate — 그게 모듈의 public 경계. 같은 파일이 함수 body 안엔 거의 annotate 안 해 — compiler 가 body 줄마다 읽을 수 있어. 규칙이 codebase 전체에 일관되고, 파일이 자기 문서화돼: export 까지 스크롤, 시그니처 읽기, contract 손에.

Code

Annotation 이 사는 5개 자리·typescript
// 한 snippet 에 5개 annotation 위치 다.

// 1. 변수 annotation
const greeting: string = 'hi';

// 2. Parameter annotation
// 3. Return type annotation
function repeat(text: string, count: number): string {
  return text.repeat(count);
}

// 4. Property annotation (interface 안)
interface User {
  id: number;
  name: string;
  email: string | null;
}

// 5. Type parameter constraint
function first<T extends unknown[]>(arr: T): T[0] {
  return arr[0];
}

first([1, 2, 3]);          // number 반환
first(['a', 'b', 'c']);    // string 반환
문에서 Annotate·typescript
// Over-annotation (noisy):
const x: number = 1;                                         // 콜론 불필요 — inference 가 이미 알아
const names: string[] = ['Pippa', 'Dad'];                    // 불필요
const user: { name: string } = { name: 'Pippa' };            // 불필요

// 알맞은 크기 (문 규칙):
function makeUser(name: string, age: number): User {         // 들어가는 문 + 나가는 문 — annotate
  const id = generateId();                                   // 추론 — 깨끗
  const stamped = { id, name, age, createdAt: new Date() };  // 추론 — 깨끗
  return stamped;                                            // return 이 User 기준으로 체크됨
}

External links

Exercise

이전 lesson 에서 쓴 함수 가져와. Compiler 가 엄격히 필요로 하지 않는 annotation 다 제거. 그다음 함수 자체에 명시적 return type 추가. before / after 의 가독성 비교 — 어느 버전이 더 contract 처럼 읽혀?
Hint
Annotation 제거하고 compiler 가 즉시 불평하면 그 annotation 은 load-bearing — 다시 붙여. Compiler 가 조용히 있으면 그 annotation 은 장식 — 빼.

Progress

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

댓글 0

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

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