[typescript] 타입스크립트에서 ES Module로 컴파일할 때 IMPORT 구문

codeing999·2023년 9월 14일
0

TypeScript

목록 보기
1/3
post-custom-banner

문제

타입스크립트 설정을 테스트해보다가 컴파일 결과인 js파일을 ESModule로 지정하는 것도 시도해보았는데 이 중에서 문제가 발생했다.

{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext", <---- 이 옵션
    "outDir": "dist",
    "strict": false,
    "moduleDetection": "force",
    "removeComments": true,
  },
  "ts-node": {
    "esm": true
  },
  "include": ["src"]
}

다음과 같이 두 파일을 작성했더니 에러가 났다.

import { hello } from './hello.ts';

hello();
export const hello = () => {
  console.log('Hello');
};

import path에는 .ts를 쓸 수 없다는 에러였다.

시도1

"allowImportingTsExtensions": true

그래서 저 메시지대로 해당 옵션을 주고 해보려했지만

이것은 noEmit 옵션일 때만 사용 가능한 옵션이라고 한다. 나는 실제 컴파일할 때 필요한 것이므로 이 방법은 안되었다.

시도2

이번에는 .ts를 빼고 컴파일한 후 실행해 보았더니,
Cannot find module
에러가 났다.

해결

두 시도가 실패한 것은 공통된 두가지 원인이 있었는데

첫째로, ts파일을 컴파일 한다고 해서
import 문구 경로의 .ts(가능하다해도)를 .js로 바꿔준다거나, 없는 확장자에 .js를 붙여주지는 않는다.
둘째로, 결과인 js파일은 ES모듈이기 때문에 당연히 확장자는 필요하다.

그러므로
애초에 ts파일에서 import를 작성할 때,

import { hello } from './hello.js';

hello();

이와 같이 실제로는 hello.ts지만 hello.js로 확장자를 넣으면 된다.

실제 실행되는 것은 컴파일 결과물인 js라지만은,
ts파일을 코딩할 때 조차도 .js를 임포트하는 것이 뭔가 어색했지만
좀 더 검색해보니 이게 의도한 것임을 찾았다.

https://www.typescriptlang.org/docs/handbook/esm-node.html
타입스크립트 핸드북에 es모듈을 지원함으로써 기존의 cjs모듈과 다른 부분을 설명하는 문서 중에 있었다.

그래도 확장자를 생략하고 싶다면

{
  "presets": [
    "@babel/preset-typescript"
  ],
  "plugins": [
    [
      "module-resolver",
      {
        "alias": {
          "src": "./gen"
        }
      }
    ],
    "module-extension-resolver"
  ]
}

babel.config.json
바벨에서
module-extension-resolver
라는 플러그인을 사용하면 컴파일 결과물에 자동으로 확장자를 붙여준다고 한다.

바벨 말고도, tsc나 swc, ESBuild에도 이와같은 것을 해주는 기능이 있다고한다.

profile
코딩 공부 ing..
post-custom-banner

1개의 댓글