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

Native TypeScript — --experimental-strip-types

~11 min · modern-node, typescript, strip-types

Level 0노드 입문자
0 XP0/40 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"Node 22 가 TypeScript 직접 실행 능력 추가. 완전한 TypeScript 지원 아냐 — 타입 벗기고 밑의 JavaScript 돌려. 대부분 코드엔 그게 충분."

`--experimental-strip-types` 가 하는 일

Node 22 가 --experimental-strip-types 도입. Node 24 가 stabilize. Node 26 기준 .ts 파일 직접 실행 가능:

// hello.ts
type Greeting = { msg: string; from: string };

function greet(g: Greeting): string {
  return `${g.from} says: ${g.msg}`;
}

console.log(greet({ msg: 'hi', from: 'Pippa' }));
node --experimental-strip-types hello.ts
# Pippa says: hi

런타임이 파일 파싱, 타입 어노테이션 제거, 남은 JavaScript 실행. 타입 체크 안 함. 지원 안 되는 기능 (decorator, namespace, enum) 의 transpilation 안 함. 그냥 type erasure.

되는 거, 안 되는 거

됨:

  • 타입 어노테이션: const x: number = 5
  • Interface: interface Foo { x: number }
  • Type alias: type Foo = { x: number }
  • Generic: function id<T>(x: T): T { return x; }
  • satisfies, as assertion, type import

안 됨 (strip-types 모드):

  • Enum (enum X { a, b }) — 타입만이 아닌 런타임 코드로 컴파일.
  • 값 있는 namespace (순수 type-only 아닌 TS namespace).
  • Decorator (제안 단계의 TC39 decorator 가 다른 의미론).
  • JSX — 별도 transformer 필요.

Enum 과 decorator 피하는 대부분 애플리케이션 코드엔 strip-types 가 커버. Enum 무거운 API 라이브러리 코드 (옛 Angular, NestJS) 엔 여전히 진짜 TS 컴파일러 필요.

TS-As-Linter 전략

타입 체크엔 strip-types 와 tsc --noEmit 페어:
  • 실제 프로그램 실행은 node --experimental-strip-types (Node 가 실행, 타입은 장식).
  • CI 와 pre-commit 에선 tsc --noEmit (TypeScript 가 타입 검증, 아무것도 emit 안 함).
타입 에러는 CI 실패; 런타임 에러는 런타임에 실패. 두 역할이 깨끗하게 분리. 더 이상 ts-node, tsx, esbuild-register, 또는 다른 transpile-on-import hook 안 필요. TypeScript 컴파일러가 순수 linter 됨; Node 가 코드 돌림.

이게 2026 의 Node + TypeScript 최고로 깨끗한 dev 경험. Transpile-on-import 보다 빠름 (실행당 추가 프로세스 없음), build-step setup 보다 단순, 모든 타입 안전성 유지.

.ts / .mts / .cts 관례

.js / .mjs / .cjs 와 같음:

  • .mts — 항상 ESM
  • .cts — 항상 CJS
  • .ts — 가장 가까운 package.json 의 type 필드 따름

새 프로젝트엔 package.json 에 "type": "module" 설정하고 어디든 plain .ts 써. 런타임이 ESM 으로 다루고, 타입 체커가 만족하고, 확장자 생각 안 해도 돼.

플래그 결합 — 풀 모던 stack

완전한 "모던 Node dev" 명령:

node \
  --experimental-strip-types \
  --env-file=.env \
  --watch \
  --enable-source-maps \
  server.ts

이게 대체: ts-node, dotenv, nodemon, esbuild-register, source-map-support. npm 패키지 다섯, 사라짐. package.json 스크립트가 Node 릴리스마다 더 짧아져.

Pippa 의 고백

Node 22 가 이거 출하했을 때 내 첫 반응은 "흥미로운데 내 프로젝트는 이미 Vite/tsx 써." 아빠가 밀어붙임: "tsx 와 Vite 가 실제로 strip-types 가 안 하는 뭘 해?" 백엔드 코드엔 답이 대부분 "유용한 거 없음." 둘 다 TS 컴파일러 출하 — 200MB 들고 이제 런타임이 공짜로 하는 일 함. tsx 쓰던 cwkPippa 백엔드 스크립트가 node --experimental-strip-types 로 전환하고 dev 시작이 빨라짐 — 컴파일러 warm-up 없음. 또 교훈: 네 도구 정당화가 아직 유효한지 검사해.

Code

strip-types 워크플로 위한 tsconfig + script·json
// tsconfig.json for a project using strip-types + tsc-as-linter
{
  "compilerOptions": {
    "target": "esnext",
    "module": "nodenext",
    "moduleResolution": "nodenext",
    "strict": true,
    "noEmit": true,                 // tsc only checks; doesn't emit
    "allowImportingTsExtensions": true,  // import './foo.ts' is OK
    "verbatimModuleSyntax": true,   // play nice with strip-types
    "isolatedModules": true,
    "esModuleInterop": true
  },
  "include": ["src/**/*"]
}

// package.json scripts
//   "dev":   "node --experimental-strip-types --env-file=.env --watch src/server.ts",
//   "start": "node --experimental-strip-types --env-file=.env.production src/server.ts",
//   "check": "tsc --noEmit",
//   "test":  "node --experimental-strip-types --test src/**/*.test.ts"
Plain TypeScript 를 Node 가 직접 실행·typescript
// A real TS file that strip-types handles
import { readFile } from 'node:fs/promises';

interface Config {
  port: number;
  hosts: readonly string[];
  database: {
    url: string;
    poolSize: number;
  };
}

async function loadConfig(path: string): Promise<Config> {
  const raw = await readFile(path, 'utf-8');
  return JSON.parse(raw) as Config;
}

const config = await loadConfig('./config.json');
console.log(`starting on port ${config.port}`);
config.hosts.forEach((h: string) => console.log(`  - ${h}`));

External links

Exercise

현재 dev 에 tsx 또는 ts-node 쓰는 작은 TypeScript 프로젝트 골라. Dev 스크립트를 node --experimental-strip-types 로 전환. 기존 테스트 돌려; 변경 없이 통과해야 함. 둘의 cold startup 시간 재 — strip-types 가 두 번째 invocation 에서 눈에 띄게 빠를 거야, transpiler warm-up 없으니까. 뭐 깨지면 (a) enum 사용 또는 (b) import 의 누락 .ts 확장자 의심.
Hint
Enum 은 코드베이스에서 enum 검색 — 있으면 as const literal-typed 객체 (strip-types 와 작동) 로 교체할지 tsx 계속 쓸지 결정. 확장자 import 는 tsconfig 가 allowImportingTsExtensions: true 필요하고 import 가 명시적 .ts 확장자 필요. codemod 스크립트가 한 번에 import 경로 다시 쓸 수 있어.

Progress

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

댓글 0

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

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