selmertsxの素振り日記

ひたすら日々の素振り内容を書き続けるだけの日記

TypeScript 2.7での esModuleInteropをつけたコンパイルの挙動

モチベーション

GitHub - selmertsx/serverless-prpolice

個人プロダクトの開発中に、TypeScriptのコードが buildすると実行できるのに、Jestのテストだけコケるという問題が発生した。その原因を調査したかった。

前提条件

"typescript": "^2.7.1"

問題の内容

consoleの内容

# 呼び出し元のコード
import { GitHubApi } from "@octokit/rest";
const github = new GitHubApi();
github.authenticate({...})
$ yarn test
yarn run v1.3.2
$ jest
 PASS  __tests__/github.spec.ts
  pullRequests
    ✓ get (850ms)
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        4.1s, estimated 6s
$ bin/prpolice local get_pr
(node:1) UnhandledPromiseRejectionWarning: 
Unhandled promise rejection (rejection id: 1): TypeError: rest_1.default is not a constructor

調査

# buildされたコード
Object.defineProperty(exports, "__esModule", { value: true });
var rest_1 = require("@octokit/rest");
var pull_request_1 = require("./pull_request");
var GitHub = (function () {
    function GitHub(owner, repo) {
        this.github = new rest_1.default();

https://github.com/octokit/rest.js/blob/master/index.js

module.exports = GitHubApi
function GitHubApi (options) {
  ....
end

Compiler Options · TypeScript

Emit importStar and importDefault helpers for runtime babel ecosystem compatibility and enable --allowSyntheticDefaultImports for typesystem compatibility.

# --esModuleInterop をつけてコンパイルされたコード
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
}
Object.defineProperty(exports, "__esModule", { value: true });
var rest_1 = __importDefault(require("@octokit/rest"));
var pull_request_1 = require("./pull_request");
var GitHub = (function () {
    function GitHub(owner, repo) {
        this.github = new rest_1.default();
        this.owner = owner;
        this.repo = repo;
    }
# コンパイルされたコードの挙動の確認
$ node
> const a = { "default": require("@octokit/rest") }
undefined
> a.default
[Function: GitHubApi]
> a.default()
{ hook:
   { [Function: bound register]

このコードで、jestも sam localのテストも動くことが確認できました。