"반쯤 strict 한 TypeScript 는 없어. 너의 버그를 찾는 TypeScript 와, 찾는 척하는 TypeScript 만 있어."
가장 중요한 단일 `tsconfig` flag
`tsconfig.json` 에 옵션 하나만 설정하면, "strict": true 설정해. 그 단일 flag 가 7개의 별개 체크를 켜 — TypeScript 가 "문법만 추가된 JavaScript" 쓰는 동안 끄덕거리는 대신 실제로 타입 에러를 잡게 만드는 그 체크들. Strict mode 는 자기 몫을 하는 type system 과 장식용 type system 사이의 선이야.
이 flag 가 켜는 7개: noImplicitAny (annotation 없는 parameter 나 return value 금지), strictNullChecks (null 과 undefined 는 다른 모든 타입과 분리), strictFunctionTypes (함수 parameter 가 contravariantly 체크), strictBindCallApply (`call` / `apply` / `bind` 가 argument 체크), strictPropertyInitialization (class field 는 constructor 에 assign 되거나 optional 표시 필수), noImplicitThis (annotation 없는 `this` 금지), useUnknownInCatchVariables (`catch (e)` 가 `any` 아니라 `unknown` 줘).
나중에 켜는 게 처음부터 켜는 것보다 어려운 이유
`strict` 없이 TypeScript 5,000 줄 썼다고 상상해. 함수 절반이 implicit `any` parameter. 코드 대부분이 null 아닌 거 가정. Class field 어느 것도 초기화 체크 안 됨. 이제 `strict: true` 켜. Compiler 가 에러 600개 보고. 2주 동안 한 번에 하나씩 고치는 동안 아무것도 ship 안 함.
대신, 첫 commit 에 `strict: true` 설정 상상. 네가 쓴 모든 줄이 그 아래에서 체크됐어. 600개 에러 절벽이 존재하지 않아, 도움 없이 그 정도까지 간 적 없으니까. 총 작업량은 같아 — 비용을 끝에서 한 덩어리로 내는 대신, 쓰면서 줄마다 내는 거.
교훈 단순해: strict 로 시작해, strict 유지해. 모든 프로젝트. 모든 repo. 예외 없음.
레슨마다 실제로 느껴지는 것
가장 많이 느낄 변화: strictNullChecks. 없으면 모든 변수가 조용히 null 될 수 있어. 있으면 compiler 가 null 될 수 있는 곳마다 처리하라고 강제해. if (x !== null) 체크 더 많이 쓰게 돼. 또한 빠진 필드가 production 깨는 버그도 더 이상 ship 안 해.
2번째: noImplicitAny. 없으면 annotation 없는 parameter 가 조용히 `any` 로 타입 (즉, "체크하지 마"). 있으면 compiler 가 annotation 스킵하는 거 거부. 2주 동안 아프고, 영원히 자유로워.
가장 새로운 거 (TS 4.4+): useUnknownInCatchVariables. 없으면 catch (e) 가 `e: any` 줘. 있으면 `e: unknown` 줘 — 쓰기 전에 narrow 하라고 강제. 이 단일 체크가 다른 어느 것보다 더 많은 늦은 밤 log 파기를 줄였어.
Strict 아닌 프로젝트 물려받을 때
`strict: true` 안 켜고 7개 sub-flag 한 번에 하나씩 켤 수 있어. strictNullChecks 부터 시작 (impact 가장 크고, retrofit 가장 어려움). 그다음 noImplicitAny. 그다음 나머지. 각각이 뭘 고쳐야 하는지 알려줘. 프로젝트가 각각 개별로 깨끗해지면 `strict: true` 켜고 per-flag 설정 제거.