최종 수정일 : 2021년 9월 8일
!주의 이 문서는 유익하지 않습니다(?).
allowSyntheticDefaultImports
esModuleInterop
forceConsistentCasingInFileNames
isolatedModules
preserveSymlinks
true
로 하면, allowSyntheticDefaultImports
는 이렇게 import
하는 것을 허용합니다:
import React from "react";
대신:
import * as React from "react";
모듈이 default export
를 명시하지 않은 경우.
예를 들어, allowSyntheticDefaultImports
를 사용하지 않을 때:
// @filename: utilFunctions.js
>> Module '"/home/runner/work/TypeScript-Website/TypeScript-Website/utilFunctions"' has no default export.
const getStringLength = (str) => str.length;
module.exports = {
getStringLength,
};
// @filename: index.ts
import utils from "./utilFunctions";
const count = utils.getStringLength("Check JS");
이 코드는 import 할 수 있는 default
객체가 없기 때문에 에러를 일으킵니다. 그럼에도 불구하고, 할 수 있을 것 처럼 느껴집니다. 편의를 위해, 바벨같은 트랜스파일러는 default
가 없다면 자동적으로 default
를 생성합니다. 모듈을 좀 더 비슷하게 만들기:
// @filename: utilFunctions.js
const getStringLength = (str) => str.length;
const allFunctions = {
getStringLength,
};
module.exports = allFunctions;
module.exports.default = allFunctions;
이 플래그는 TypeScript가 JavaScript를 내보내는데 영향을 주지 않고, 오직 타입 확인에만 영향을 줍니다. extra code에서 바벨과 함께 TypeScript가 좀 더 인체공학적으로 사용하도록 모듈의 default export
를 만들어서 내보내도록 합니다.
기본적으로(esModuleInterop
가 false이거나 설정되지 않음) TypeScript는 CommonJS/AMD/UMD 모듈을 ES6 모듈과 비슷하게 취급합니다. 이를 통해, 잘못된 가정임이 밝혀진 두 파트가 있습니다:
import * as moment from "moment"
처럼 import 하면 const moment = require("moment")
와 동일하게 동작한다.import moment from "moment"
처럼 기본적인 import는 const moment = require("moment").default
와 동일하게 동작한다.이 불일치는 두 가지 이슈를 유발합니다:
import * as x
)는 오직 object만 가능하고, TypeScript는 import를 = require("x")
와 동일하게 취급하여 호출 가능한 함수처럼 취급합니다. 이것은 스펙의 권장 사항을 위반합니다.esModuleInterop
을 활성화하면 TypeScript가 코드를 트랜스파일하며 문제를 해결합니다. 첫번 째는 컴파일러의 동작을 변경하고, 두번 째는 내보낸 JavaScript의 호환성의 보장을 제공하는 두 가지 헬퍼 함수에 의해 해결됩니다:
import * as fs from "fs";
import _ from "lodash";
fs.readFileSync("file.txt", "utf8");
_.chunk(["a", "b", "c", "d"], 2);
esModuleInterop
를 비활성화 했을 때:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const fs = require("fs");
const lodash_1 = require("lodash");
fs.readFileSync("file.txt", "utf8");
lodash_1.default.chunk(["a", "b", "c", "d"], 2);
esModuleInterop
를 true
로 활성화 했을 때:
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs = __importStar(require("fs"));
const lodash_1 = __importDefault(require("lodash"));
fs.readFileSync("file.txt", "utf8");
lodash_1.default.chunk(["a", "b", "c", "d"], 2);
주의: namespace import import * as fs from "fs"
는 import된 object가 보유한 속성들만을 위해 등록합니다(기본적으로 prototype 체인이 아닌 object에 등록된 속성). 상속된 속성을 사용하는 API가 정의된 모듈을 import 하는 중이고, 기본 import 형태(import fs from "fs"
) 사용을 필요로 하거나, 또는 esModuleInterop
을 비활성화하는 경우.
주의: importHelpers를 활성화하여 간결한 JS를 내보낼 수 있습니다:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const fs = (0, tslib_1.__importStar)(require("fs"));
const lodash_1 = (0, tslib_1.__importDefault)(require("lodash"));
fs.readFileSync("file.txt", "utf8");
lodash_1.default.chunk(["a", "b", "c", "d"], 2);
esModuleInterop
를 활성화하면 allowSyntheticDefaultImports도 활성화 됩니다.
TypeScript는 실행 중인 파일 시스템의 대/소문자 구분 규칙을 따릅니다. 일부 개발자는 대/소문자를 구분하는 파일 시스템에서 작업하고 다른 개발자는 그렇지 않은 경우 이 문제가 발생할 수 있습니다. 파일이 ./FileManager.ts
를 fileManager.ts
라고 import 할 경우 파일은 대/소문자를 구분하지 않는 파일 시스템에서 찾을 수 있지만 대/소문자를 구분하는 파일 시스템에서는 찾을 수 없습니다.
이 옵션을 사용하면, 프로그램이 디스크에 있는 파일과 다른 대/소문자로 포함하려 하면 TypeScript는 에러를 일으킬 것입니다.
TypeScript를 이용하여 TypeScript 로 부터 JavaScript 코드를 만들 수 있지만, Babel 같은 다른 트랜스파일러도 일반적으로 사용합니다.
하지만, 다른 트랜스파일러는 한 번에 하나의 파일에서만 작동하므로 전체 시스템을 이해해야 하는 코드 변환을 적용할 수 없습니다.
이 제한은 일부 빌드 도구에서 사용하는 TypeScript의 ts.transpileModule
API 에도 적용됩니다.
이러한 제한으로 인해 const enum
및 namespace
와 같은 일부 TypeScript 기능에 런타임 문제가 발생할 수 있습니다. isolatedModules
플래그를 설정하면 단일 파일 변환 프로세스에서 제대로 해석할 수 없는 코드를 작성할 경우 TypeScript에 경고를 표시합니다.
코드 동작이나 TypeScript의 검사 및 내보내기 프로세스의 동작은 변경되지 않습니다.
isolatedModules
를 활성화 할 때 작동하지 않는 코드의 몇 가지 예시입니다.
TypeScript에서는, 타입을 import 할 수 있고 그 후에 export 할 수도 있습니다:
import { someType, someFunction } from "someModule";
someFunction();
export { someType, someFunction };
왜냐하면 거기엔 someType
을 위한 값이 없기 때문에, export
는 export를 시도하지 않습니다 (아마도 JavaScript에서 런타임 오류일 것입니다):
export { someFunction };
단일 파일 트랜스파일러는 someType
이 값을 생성했는지 아닌지 여부를 알 수 없기 때문에, 타입만 참조하는 이름을 export 것은 에러입니다.
isolatedModules
이 비활성화일 때, 구현된 모든 파일은 반드시 모듈이어야 합니다 (import
/export
형태여야 한다는 뜻). 파일이 모듈이 아닐 경우 에러가 발생합니다:
function fn() {}
>> 'index.ts' cannot be compiled under '--isolatedModules' because it is considered a global script file. Add an import, export, or an empty 'export {}' statement to make it a module.
.d.ts
파일은 이 제한이 적용되지 않습니다.
TypeScript는 const enum
멤버의 참조는 제거하고 실제 값을 JavaScript로 내보냅니다.
이레 TypeScript는:
declare const enum Numbers {
Zero = 0,
One = 1,
}
console.log(Numbers.Zero + Numbers.One);
아래 JavaScript로 변환됩니다:
"use strict";
console.log(0 + 1);
이 멤버들의 값들 모른다면 다른 트랜스파일러들은 Numbers
의 참조를 대체할 수 없습니다.
그대로 두면 런타임 에러가 발생됩니다(런타임에 Numbers
객체가 없어서).
왜냐하면, isolatedModules
이 사용될 때 const enum
멤버를 참조하면에러가 발생합니다.
이것은 Node.js에서 동일한 플래그를 반영합니다; symlink의 실제 경로를 확인하지 않습니다.
이 플래그는 또한 Webpack의 resolve.symlinks
옵션의 반대 행동을 보입니다(TypeScript의 preserveSymlinks
를 true
로 두고 Webpack의 resolve.symlinks
를 false
로 하거나, 반대의 경우도. 다시 말해, 우리는 이 문제를 해결할 수 있는 것이 아닙니다.).
이것을 활성화하면, 모듈과 패키지의 참조는(예: import
와 /// <reference type="..." />
를 지시하는) 심볼릭 링크가 확인되는 경로보다는, 심볼릭 링크 파일의 위치를 모두 확인합니다.