C.W.K.
Stream
Lesson 04 of 07 · published

TypeScript 6 Strict — React + Async + SSE 타이핑

~16 min · typescript, strict, types

Level 0호기심
0 XP0/65 lessons0/17 achievements
0/100 XP to next level100 XP to go0% complete

Strict 모드는 옵션 아냐

cwkPippa 의 모든 tsconfig.json"strict": true. 협상 X. 이유는 dogma 아니고 — strict 가 컴파일 타임에 잡는 버그가 새벽 2시에 재현 안 되는 그 버그들이거든.

strictNullChecks 는 'cannot read property of undefined' 패밀리 잡아. noImplicitAny 는 sloppy 한 parameter 하나가 call graph 전체에 any 새는 거 막아. strictFunctionTypes 는 함수 파라미터 variance 를 정직하게 만들어.

Discriminated union 으로 server 메시지 모델링

backend 의 SSE stream 은 typed event 보내: text delta, tool use, tool result, error, 마지막 done. 한 discriminated union 으로 모델링하는 게 frontend 코드를 진짜 안전하게 만드는 방법 — TypeScript 가 각 switch arm 안에서 type 좁혀, case 빠뜨릴 수 없어 (noFallthroughCasesInSwitch: true 박으면 buggy switch 못 박음).

Generic hook — inference 안 잃고 typed

custom hook 은 generic 받게 해서 caller 가 type 정보 안 잃게. useFetch<T>()useFetch()any 반환하는 것보다 옳음.

원칙: any 로 끝나는 type 은 존재하지 않는 type. as any 손 댈 때 멈춰서 *진짜로* 어떤 contract 원하는지 생각해. 가끔 답은 unknown + runtime guard. 그래도 any 보단 나아.

Code

Discriminated union for SSE events·ts
type SSEEvent =
  | { type: 'delta'; text: string }
  | { type: 'thinking'; text: string }
  | { type: 'tool_use'; name: string; input: unknown }
  | { type: 'tool_result'; tool_use_id: string; output: string }
  | { type: 'usage'; input_tokens: number; output_tokens: number }
  | { type: 'emotion'; emotion: string }
  | { type: 'done' }
  | { type: 'error'; message: string };

function handleEvent(e: SSEEvent) {
  switch (e.type) {
    case 'delta': return appendText(e.text);
    case 'thinking': return appendThinking(e.text);
    case 'tool_use': return startTool(e.name, e.input);
    case 'tool_result': return finishTool(e.tool_use_id, e.output);
    case 'usage': return recordCost(e.input_tokens, e.output_tokens);
    case 'emotion': return setAvatarEmotion(e.emotion);
    case 'done': return finalize();
    case 'error': return showError(e.message);
    // exhaustive — TS errors if a case is missing
  }
}

Progress

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

댓글 0

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

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