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

tsconfig Strict — 모든 플래그 설명

~16 min · typescript, tsconfig, strict, react

Level 0React 입문자
0 XP0/54 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
TypeScript 의 strict 모드는 boolean 하나인 척하는 체크 여덟 개야. 어떤 체크가 발동했는지 알아보는 게 — 버그 고치기랑 메신저 죽이기의 차이.

`strict: true` 가 실제로 켜는 것들

Vite scaffold 가 tsconfig.app.jsonstrict: true 줘. 그 플래그 하나가 묶음을 켜. TypeScript 6.0 기준 묶음은:

  • noImplicitAny — 모든 파라미터/변수에 명시적 또는 추론 가능한 타입 필요. 조용한 any 금지.
  • strictNullChecksnull/undefined 가 더는 모든 타입에 할당 안 돼. 명시적으로 넓혀야 함 (string | null).
  • strictFunctionTypes — 함수 파라미터가 contravariant 하게 체크 돼. 교묘한 서브클래스 substitution 버그 차단.
  • strictBindCallApply.bind()/.call()/.apply() 인자 타입 체크.
  • strictPropertyInitialization — 클래스 필드가 생성자에서 할당 돼야 함 (또는 ! 표시).
  • noImplicitThisthis 가 암시적 any 면 에러.
  • alwaysStrict — 모든 파일 상단에 "use strict" emit (파싱에도 영향).
  • useUnknownInCatchVariablescatch (e)any 대신 unknown — narrowing 강제.

여덟 개 다 외울 필요 없어. TS 에러 메시지 읽을 때 어느 체크가 발동했는지 메시지가 이름 대고 있다는 걸 알면 충분해.

React-specific TS 설정

strict 외에 React 에 중요한 셋:

  • "jsx": "react-jsx" — 모던 JSX transform. JSX 쓰려고 모든 파일에 import React from 'react' 더는 필요 없어.
  • "moduleResolution": "bundler" — TypeScript 가 Vite/esbuild/Rollup 처럼 import 해석 (.js 확장자 필요 없음).
  • "target": "ES2022" 이상 — top-level await, private class fields 같은 모던 JS 를 down-level 없이 쓸 수 있음.

Vite scaffold 의 분할: app + node config

tsconfig 세 개 보일 거야: tsconfig.json (root reference manifest), tsconfig.app.json (src/ 코드용), tsconfig.node.json (Vite config 파일들 자체용, Node 에서 돔). 분할 이유: Node 의 vite.config.ts 와 브라우저-바인딩된 React 코드가 다른 DOM lib 요구사항을 가져서. 합치지 마.

strict-mode 에러 읽기

Argument of type 'string | undefined' is not assignable to parameter of type 'string'. 보이면 — strictNullChecks 가 말하는 거야. 고침: guard 로 narrow (if (value === undefined) return;), 디폴트 제공 (value ?? ""), 또는 파라미터 타입을 undefined 받게 넓힘. ! (non-null assertion) 으로 억제 금지 — 이 시점에 값이 undefined 가 아님을 실제로 검증한 게 아니면.

! 함정. Postfix ! 는 TypeScript 의 '믿어, 이거 null 아냐' 연산자. 타입 체커 입은 막지만 런타임은 여전히 터질 수 있어. 코드의 모든 ! 는 진 빚이야. 진짜 guard 추가해서 갚아.

Code

tsconfig.app.json — Vite scaffold 기본, 어노테이션·json
{
  "compilerOptions": {
    "target": "ES2022",
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "moduleResolution": "bundler",
    "jsx": "react-jsx",

    /* strict 체크 여덟 개를 플래그 하나로 */
    "strict": true,

    /* 린팅 (strict 아닌 경고들) */
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,

    /* Bundler 친화: TS 는 JS emit 안 함, Vite 가 처리 */
    "noEmit": true,
    "isolatedModules": true,
    "allowImportingTsExtensions": true,
    "verbatimModuleSyntax": true
  },
  "include": ["src"]
}
각 strict 체크가 잡는 실제 React 버그·tsx
// strictNullChecks — 없으면, undefined 일 수 있는 user 의 .name 접근이
// 조용히 컴파일되고 런타임에 터져.
function Greet({ user }: { user?: { name: string } }) {
  // 컴파일러 거부: user 가 possibly undefined.
  // return <p>Hello, {user.name}</p>;

  // 올바른 패턴: 먼저 narrow.
  if (!user) return <p>Hello, friend</p>;
  return <p>Hello, {user.name}</p>;
}

// useUnknownInCatchVariables — catch (e) 가 any 아니라 unknown 줌.
async function loadOrLog() {
  try {
    await fetch("/api/data");
  } catch (e) {
    // 'e' 는 unknown. 바로 .message 못 함.
    const message = e instanceof Error ? e.message : String(e);
    console.error(message);
  }
}

External links

Exercise

Lesson 3 의 부트스트랩 프로젝트에서 tsconfig.app.json 열어서 일시적으로 strict: truestrict: false 로 바꿔. 타입 어노테이션 없는 파라미터 받는 함수 (function shout(msg) { return msg.toUpperCase(); }) 추가하고 shout(null) 로 호출. 이제 컴파일되는 거 확인. strict 복원. 타입 어노테이션 (msg: string) 추가하고 컴파일러가 null 호출에 대해 뭐라 하는지 봐.
Hint
strict 끄면 파라미터가 any 로 추론 돼. strict 켜고 어노테이션 있으면 호출 지점 가리키며 'Argument of type null is not assignable' 에러 나옴.

Progress

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

댓글 0

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

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