노트

verbatimModuleSyntax와 import type

verbatimModuleSyntax

프런트엔드#ts#tooling · 연결된 개념 5개

쉽게 말하면

verbatimModuleSyntax는 import마다 '이건 타입이라 빌드 때 버려도 돼요' 표시를 직접 붙이게 하는 옵션이에요. 이삿짐 상자에 '버릴 것' 스티커를 붙여 두면 내용물을 모르는 일꾼도 실수 없이 치울 수 있는 것과 같죠.

비유가 깨지는 곳 일꾼이 내용물을 모르는 이유는 esbuild·SWC처럼 파일 하나씩 변환하는 도구가 다른 파일을 보지 않기 때문이에요. 표시 없는 import는 쓴 그대로 남으니 타입만 가져올 땐 import type을 꼭 써요.

verbatimModuleSyntax(TypeScript 5.0+)는 import/export를 쓴 그대로 출력에 남기라고 강제하는 컴파일러 옵션이다. 대신 타입만 가져오는 import에는 type을 직접 표시해야 한다. import type으로 표시한 것만 지워진다.

import type { User } from './types'          // 통째로 지워짐
import { fetchUser, type Query } from './api' // fetchUser만 남음
import { User } from './types'               // ❌ 타입인데 type 표시가 없음
  • 왜 필요한가: 원래 tsc는 프로젝트 전체를 보고 "이 import는 타입으로만 쓰였다"를 판단해 알아서 지웠다. 그런데 esbuild·SWC(Speedy Web Compiler)·Babel처럼 파일 하나씩 변환하는 도구는 다른 파일을 보지 않아서 그 판단을 할 수 없다. 표시를 강제하면 어떤 도구로 변환해도 결과가 같다
  • 읽는 사람도 import가 값인지 타입인지 바로 안다
  • 예전 옵션 importsNotUsedAsValues와 preserveValueImports를 대체한다
  • 같은 문제의식의 옵션이 isolatedModules다. 파일 단위로 안전하게 변환할 수 없는 코드(다른 파일의 const enum 참조, 타입만 re-export 등)를 에러로 알려 준다
  • import './polyfill'처럼 부수 효과만 있는 import는 그대로 남는다. CommonJS로 출력하는 경우에는 쓸 수 있는 문법에 추가 제약이 생기므로 ESM(ECMAScript Modules) 출력(module: esnext·nodenext)과 함께 쓰는 것이 자연스럽다

모듈 문법은 ES 모듈과 CommonJS, 타입 검사를 따로 돌리는 구성은 tsc --noEmit과 타입 검사 분리.

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 배럴 파일과 re-export

    배럴 파일(Barrel File)은 여러 모듈의 export를 index.ts 하나에 모아 다시 내보내(re-export) 진입점을 하나로 만드는 파일이다. 쓰는 쪽은 import { Button, Input } from './components'처럼 한 경로에서 가져온다.

  • type과 interface

    type(타입 별칭, Type Alias)과 interface는 둘 다 타입에 이름을 붙이는 방법이다. 객체 모양을 정의할 때는 대부분 바꿔 써도 되지만, 확장 방식과 표현 범위가 다르다.

  • 기본형 집착

    전화번호·금액·우선순위 같은 도메인 개념을 끝까지 문자열이나 숫자로만 다루는 냄새. 같은 검증과 포맷 코드가 여기저기 반복되고, 문자열로 모든 걸 표현하는 "stringly typed" 코드가 된다.

  • 타입 추론과 타입 검사

    타입 추론(Type Inference)은 표기가 없어도 컴파일러가 값의 타입을 정하는 단계이고, 타입 검사(Type Checking)는 정해진(추론됐거나 명시된) 타입을 코드가 지키는지 확인하는 단계다. 보통 추론이 먼저 일어나고, 그 결과를 기준으로 검사한다.

  • TypeScript 클래스 문법

    TypeScript는 JavaScript 클래스에 접근 제어자(Access Modifier), readonly, 추상 클래스(Abstract Class), 생성자 매개변수 프로퍼티(Parameter Properties) 같은 타입 수준 문법을 더한다. 이들은 컴파일 때 검사에만 쓰이고, 출력 JS에서는 대부분 사라진다.

보기 옵션