TypeScript interop
import 문법보다 세 설정의 방향을 먼저 맞춘다
CommonJS 호환 문제는 소스 문법 하나로 끝나지 않습니다. TypeScript가 어떤 파일을 내보내는지, Node가 그 파일을 어떤 모듈로 읽는지, 타입 선언이 실제 값 모양을 어떻게 설명하는지를 함께 봅니다.
first checks
tsconfig
module, esModuleInterop
package.json
type, 실행 파일 확장자
types
.d.ts, @types,
declare module
같은 방향이어야 하는 세 축
컴파일 출력
module 옵션
CommonJS면 require 계열 출력,
ESNext나 NodeNext면 ESM 출력에
가깝습니다.
런타임 해석
Node가 읽는 방식
"type": "module", .mjs,
.cjs가 배포 파일의 모듈 의미를 결정합니다.
타입 표면
가져오기 모양
default, named import, namespace import가 실제
module.exports 모양과 맞아야 합니다.
상황별로 맞춰야 하는 조합
상황
권장 조합
사용 코드
깨질 때 보이는 신호
기존 CommonJS 패키지
module: "CommonJS"
esModuleInterop: true
import pkg from "pkg"
default가
undefined가 되거나 함수가 아니라고 나옴
객체 형태 export
타입 선언이 named member를 정확히 공개해야 함
import { add } from "./util"
타입은 통과했지만 런타임 값에 멤버가 없음
Node ESM 프로젝트
module: "NodeNext"
"type": "module"
import { value } from "./file.js"
Node가 import를 CommonJS 파일로 해석하거나 확장자를 못 찾음
타입 없는 JS 모듈
@types 설치 또는 declare module 작성
import lib from "legacy-lib"
모든 값이
any로 퍼져 상호 운용 오류가 늦게 발견됨
실제 프로젝트에서 확인하는 순서
01
소스 import 고정
default, named, namespace 중 하나로 팀 규칙을 정합니다.
02
dist 출력 확인
exports, require,
import 중 무엇이 남는지 봅니다.
03
Node 실행 규칙 확인
배포 환경의
type과 확장자가 출력 형식과 맞는지
봅니다.
04
타입 선언 보강
호환을
any로 덮지 말고 선언 파일로 값 모양을
고정합니다.