4.4 KiB
4.4 KiB
id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
| id | title | category | status | source_trust_level | verification_status | created_at | updated_at | tags | tech_stack | applied_in | aliases | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ts-tsconfig-strategy | tsconfig 전략 — strict / paths / project references | Coding | draft | B | conceptual | 2026-05-09 | 2026-05-09 |
|
|
|
tsconfig 전략
디폴트로 켜야 할 것: strict / noUncheckedIndexedAccess / exactOptionalPropertyTypes. 모노레포면 project references. 빌드 도구가 type-check 안 해줌 →
tsc --noEmitCI 필수.
📖 핵심 개념
strict: 7개 옵션 묶음.- Compiler vs type-checker: bundler (esbuild/swc) 가 컴파일, tsc 는 검사 전담.
- Project references: 큰 monorepo 의 점진 빌드.
- Module 모드:
node16/nodenext가 ESM/CJS 정확.
💻 코드 패턴
시작 base
// tsconfig.base.json
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"lib": ["ES2023", "DOM"],
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
"exactOptionalPropertyTypes": true,
"noFallthroughCasesInSwitch": true,
"noPropertyAccessFromIndexSignature": true,
"isolatedModules": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"verbatimModuleSyntax": true,
"resolveJsonModule": true
}
}
App 별 override
// apps/api/tsconfig.json
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src",
"types": ["node"]
},
"include": ["src/**/*"],
"exclude": ["dist", "**/*.test.ts"]
}
Path alias
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@shared/*": ["../shared/src/*"]
}
}
}
런타임 호환: tsx / vite / Next.js 자동. Node 직접 실행 시 tsx 또는 tsconfig-paths/register.
Project references (monorepo)
// root tsconfig.json
{
"files": [],
"references": [
{ "path": "packages/shared" },
{ "path": "apps/api" },
{ "path": "apps/web" }
]
}
// packages/shared/tsconfig.json
{
"compilerOptions": { "composite": true, "declaration": true, "outDir": "dist" },
"include": ["src/**/*"]
}
// apps/api/tsconfig.json (참조)
{
"references": [{ "path": "../../packages/shared" }]
}
tsc --build # 모두 점진
tsc --build --watch # watch
tsc --build --clean # 정리
Type-only import (verbatimModuleSyntax)
import { type User, getUser } from './user';
// 컴파일 결과: type User 는 erased, 안전
CI type-check (bundle 따로)
- run: tsc --noEmit # type 만 검사
- run: vite build # bundle (esbuild/swc)
bundler 가 type 무시 — 별도 step.
Browser vs Node 분리
// web tsconfig
"lib": ["ES2023", "DOM", "DOM.Iterable"]
"types": [] // node types 빼기
// node tsconfig
"lib": ["ES2023"]
"types": ["node"]
Decorator (Nest 등)
"experimentalDecorators": true,
"emitDecoratorMetadata": true
또는 TS 5.0+ stage-3 decorators.
🤔 의사결정 기준
| 상황 | 옵션 |
|---|---|
| 새 프로젝트 | strict + noUncheckedIndexedAccess |
| 점진 마이그레이션 | strict 부분 켜기 (strictNullChecks 부터) |
| ESM Node 18+ | module: nodenext |
| Vite/Next | moduleResolution: bundler |
| Monorepo 큰 | project references |
| Library 배포 | composite: true, declaration: true |
❌ 안티패턴
- strict false 그대로: 의미 절반 잃음.
@ts-ignore남발: 차라리as+ 주석.any도배:unknown+ 좁히기.- path alias 만 — runtime resolver X: import 깨짐.
tsc빌드 + bundler 빌드 둘 다: 한쪽 only. tsc=check, bundler=build.skipLibCheck: false항상: node_modules 타입 깨지면 빌드 fail. 기본 true.isolatedModules: false: esbuild/swc 가 일부 패턴 못 컴파일.
🤖 LLM 활용 힌트
- strict + noUncheckedIndexedAccess + exactOptionalPropertyTypes 항상.
- bundler 컴파일 + tsc 검사 분리.
- monorepo = project references.