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

Control Flow Analysis: Compiler 가 너의 코드 읽어

~10 min · narrowing, control-flow-analysis, inference

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"우리가 본 모든 narrowing operator 가 한 재료. Control flow analysis 가 chef."

CFA 가 뭐

Control flow analysis (CFA) 가 compiler 의 코드 줄별로 읽고 모든 지점에서 각 변수의 타입 추적하는 과정. 별개 기능 아냐 — 우리가 cover 한 모든 narrowing operator 가 함께 작동하게 만드는 엔진.

Compiler 가 모든 `if` 의 모든 분기, 모든 `switch` 의 모든 `case`, 모든 early return, 모든 assignment, 모든 throw 를 걸어가. 각 연산 후, 각 변수의 타입 모델 update. Control 이 한 줄에 도달할 즈음, compiler 가 이전 모든 거 기반으로 각 변수의 가장 좁은 가능 타입을 알아.

Early return 이 함수 나머지 narrow

가장 깨끗한 CFA 패턴. 나쁜 case 체크, early return, 함수 나머지가 narrow 된 타입 봐.

function process(x: User | null) {
  if (x === null) return;
  // 여기서 함수 끝까지 x: User
  console.log(x.name);     // 안전 — x 가 non-null
}

Compiler 가 early return 읽고 추론: "이 줄 후 x 가 null 일 수 없어." 함수 나머지가 자동으로 그 제약 아래 scope.

Assignment 와 reassignment

CFA 가 assignment 도 추적. let x: string | null = getMaybe(); 다음 if (x === null) x = 'default'. if 후 `x` 가 `string` — reassignment 가 그 지점에서 가능성에서 `null` 제거.

한 미묘함: `let` 에 작동, `const` 에 안 함 (const 가 reassign 못 함). 그리고 함수 안에서만 작동 — 변수의 *선언된* 타입은 너가 쓴 거 그대로; narrowed 타입은 compiler 가 각 지점에서 추적하는 거.

함수 호출이 narrowing 리셋 (가끔)

CFA 가 함수 호출이 mutate 할 수 있다고 가정. 변수 narrow 하고, 함수 호출, 그다음 narrow 타입 쓰려고 시도하면, compiler 가 다시 넓혔을 수. 이유: 너의 narrowing 과 사용 사이, 함수 호출이 reassign 했을 수. Local 변수 (모든 write 보이는) 엔 보수적. Object property 엔 옳은 결정.

CFA 가 TypeScript 를 관료주의 대신 직관적으로 느끼게 만드는 거. 인간이 코드 읽는 방식으로 체크 쓰고, compiler 가 같은 방식으로 읽어. Narrowing operator 가 어휘; CFA 가 그것들 묶는 grammar.

Code

CFA 3가지 형태 — early return, assignment, throw·typescript
// Early return 이 함수 나머지 narrow.
function process(x: User | null) {
  if (x === null) return;
  // x: User
  console.log(x.name);
}

// CFA 가 각 assignment 추적.
function normalize(x: string | null): string {
  if (x === null) {
    x = 'default';   // 함수 나머지 narrow
  }
  return x;          // x: string
}

// Throw 도 narrow (throw 분기 절대 return 안 함).
function must(x: User | null): User {
  if (x === null) {
    throw new Error('missing user');
  }
  return x;          // x: User
}
CFA 가 리셋할 때 — 함수 호출과 property·typescript
// 함수 호출이 property 의 narrowing 리셋 가능.
interface Box { value: string | null }

function maybeReassign(b: Box) {
  b.value = null;     // 함수가 이거 할 수 있어 — compiler 가 확신 못 함
}

function process(b: Box) {
  if (b.value !== null) {
    // b.value: string
    maybeReassign(b);
    // b.value 가 string | null 로 다시 widening — 함수 호출이 mutate 했을 수
    // b.value.toUpperCase();   // ❌ 이제 null 가능
  }
}

// Local 변수엔 (compiler 가 모든 write 볼 수 있는), narrowing 이
// 함수 호출 가로질러 보존. Object property 엔 (함수가 reassign 가능한),
// narrowing 이 리셋.

External links

Exercise

x 가 null 이면 'invalid' early-return, 그다음 x 가 number 면 formatted 버전 early-return, 그다음 string 버전 default 인 handle(x: string | number | null) 함수 써. Compiler 가 hover 로 각 줄에서 x 옳게 narrow 하는지 확인.
Hint
if (x === null) return 'invalid' 후 x 는 string | number. if (typeof x === 'number') return ... 후 x 는 string. Compiler 가 early return 읽고 남은 거 추적.

Progress

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

댓글 0

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

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