사용자 도구

사이트 도구


typescript:module

Module

용어에 대한 노트: TypeScript 1.5에서 기록해둘 만큼 중요한 명명법 변경이 있었습니다. “내부 모듈(Internal modules)”은 “네임스페이스”가 되었습니다. “외부 모듈(External modules)”은 이제 간단하게 “모듈(modules)”이 되어 ECMAScript 2015의 용어와 맞췄습니다. (module X {namespace X {와 동일하며 후자가 선호됩니다.)

Introduction

ECMAScript 2015부터 JavaScript에는 모듈 개념이 있습니다. TypeScript는 이 개념을 공유합니다.

모듈은 전역 범위가 아닌 자체 범위 내에서 실행됩니다. 이는 모듈에서 선언 된 변수, 함수, 클래스 등이 내보내기 양식 중 하나를 사용하여 명시 적으로 내보내지지 않으면 모듈 외부에서 볼 수 없음을 의미합니다. 반대로, 다른 모듈에서 내 보낸 변수, 함수, 클래스, 인터페이스 등을 사용하려면 import forms 중 하나를 사용하여 가져와야합니다.

모듈은 선언적입니다. 모듈 간의 관계는 파일 수준에서 가져 오기 및 내보내기 측면에서 지정됩니다.

모듈은 모듈 로더를 사용하여 서로를 가져옵니다. 런타임시 모듈 로더는 모듈을 실행하기 전에 모듈의 모든 종속성을 찾고 실행합니다. 자바 스크립트에서 사용되는 잘 알려진 모듈 로더는 CommonJS모듈용 Node.js로더와 웹 애플리케이션에서 AMD모듈용 RequireJS로더입니다.

TypeScript에서는 ECMAScript 2015와 마찬가지로 최상위 import 또는 export가 포함 된 파일을 모듈로 간주합니다. 반대로, 최상위 import 또는 export 선언이 없는 파일은 내용이 전역 범위에서 사용할 수있는 스크립트로 취급되므로 모듈에서도 마찬가지입니다.

Export

Exporting a declaration

export 키워드를 추가하여 모든 선언 (예 : 변수, 함수, 클래스, 유형 별명 또는 인터페이스)을 내보낼 수 있습니다.

StringValidator.ts
export interface StringValidator {
    isAcceptable(s: string): boolean;
}
ZipCodeValidator.ts
import { StringValidator } from "./StringValidator";
 
export const numberRegexp = /^[0-9]+$/;
 
export class ZipCodeValidator implements StringValidator {
    isAcceptable(s: string) {
        return s.length === 5 && numberRegexp.test(s);
    }

Export statements

Export 문장은 소비자의 이름을 바꿀 필요가 있을 때 유용하므로 위의 예는 다음과 같이 작성 될 수 있습니다.

class ZipCodeValidator implements StringValidator {
    isAcceptable(s: string) {
        return s.length === 5 && numberRegexp.test(s);
    }
}
export { ZipCodeValidator };
export { ZipCodeValidator as mainValidator };

Re-exports

종종 모듈은 다른 모듈을 확장하고 일부 기능을 부분적으로 노출합니다. 다시 내보내기는 로컬로 가져 오기하거나 로컬 변수를 가져 오지 않습니다.

ParseIntBasedZipCodeValidator.ts
export class ParseIntBasedZipCodeValidator {
    isAcceptable(s: string) {
        return s.length === 5 && parseInt(s).toString() === s;
    }
}
 
// Export original validator but rename it
export {ZipCodeValidator as RegExpBasedZipCodeValidator} from "./ZipCodeValidator";

선택적으로 모듈은 하나 이상의 모듈을 랩핑하고 export * from “module”를 사용하여 모든 내보내기를 결합 할 수 있습니다.

AllValidator.ts
export * from "./StringValidator"; // exports 'StringValidator' interface
export * from "./ZipCodeValidator";  // exports 'ZipCodeValidator' and const 'numberRegexp' class
export * from "./ParseIntBasedZipCodeValidator"; //  exports the 'ParseIntBasedZipCodeValidator' class
                                                 // and re-exports 'RegExpBasedZipCodeValidator' as alias
                                                 // of the 'ZipCodeValidator' class from 'ZipCodeValidator.ts'
                                                 // module.

Import

가져 오기는 모듈에서 내보내기만큼 쉽습니다. 내 보낸 선언을 가져 오려면 아래 가져 오기 양식 중 하나를 사용하십시오.

Import a single export from module

import { ZipCodeValidator } from "./ZipCodeValidator";
let myValidator = new ZipCodeValidator();

imports는 또한 개명가능하다.

import { ZipCodeValidator as ZCV } from "./ZipCodeValidator";
let myValidator = new ZCV();

import는 전체 module을 한 변수로 받아서 export된 module을 접근할 수 있다.

import * as validator from "./ZipCodeValidator";
let myValidator = new validator.ZipCodeValidator();

Import a module for side-effects only

권장 사항은 아니지만 일부 모듈은 다른 모듈에서 사용할 수있는 일부 전역 상태를 설정합니다. 이 모듈에는 수출이 없거나 소비자가 수출에 관심이 없습니다. 이러한 모듈을 가져 오려면 다음을 사용하십시오.

import "./my-module.js";

Default exports

각 모듈은 선택적으로 default 내보내기를 내보낼 수 있습니다. default 내보내기는 키워드 default로 표시됩니다. 모듈 당 하나의 default 내보내기 만있을 수 있습니다. default import는 다른 import form을 사용하여 가져옵니다.

default 내보내기은 정말 편리합니다. 예를 들어, jQuery와 같은 라이브러리에는 jQuery 또는 $의 기본 내보내기가있을 수 있습니다. $ 또는 jQuery라는 이름으로 가져올 수도 있습니다.

JQuery.d.ts
declare let $: JQuery;
export default $;
App.ts
import $ from "jquery";
$("button.continue").html("Next Step...");

클래스 및 함수 선언은 기본 내보내기로 직접 작성 될 수 있습니다. 기본 내보내기 클래스 및 함수 선언 이름은 선택 사항입니다.

ZipCodeValidator.ts
export default class ZipCodeValidator {
  static numberRegexp = /^[0-9]+$/;
  isAcceptable(s: string) {
    return s.length === 5 && ZipCodeValidator.numberRegexp.test(s);
  }
}
Test.ts
import validator from "./ZipCodeValidator";
 
let myValidator = new validator();

or

StaticZipCodeValidator.ts
const numberRegexp = /^[0-9]+$/;
 
export default function (s: string) {
  return s.length === 5 && numberRegexp.test(s);
}
Test.ts
import validate from "./StaticZipCodeValidator";
 
let strings = ["Hello",  "98052", "101"];
 
// Use function validate
string.forEach(s => {
  console.log(`"${s}" ${validate(s) ? " matches" : " does not match"}`);
});

default내보내기는 값도 가능하다.

OneTwoThree.ts
export default "123";
Log.ts
import num from "./OneTwoThree";
 
console.log(num); // "123"

export = 와 import = require()

CommonJS와 AMD 모두 일반적으로 모듈의 모든 내보내기를 포함하는 exports 개체 개념을 가지고 있습니다.

또한 exports 개체를 사용자 지정 단일 개체로 바꾸는 기능도 지원합니다. 기본 내보내기는 이 동작을 대신하는 역할을합니다. 그러나 두 개는 호환되지 않습니다. TypeScript는 일반적인 CommonJS 및 AMD 워크 플로우를 모델링하기 위해 export =를 지원합니다.

export = 구문은 모듈에서 내 보낸 단일 객체를 지정합니다. 클래스, 인터페이스, 네임 스페이스, 함수 또는 열거 형이 될 수 있습니다.

export =를 사용하여 모듈을 내보낼 때, 모듈 가져 오기에는 TypeScript 특정 import module = require ( “module”)을 사용해야합니다.

ZipCodeValidator.ts
let numberRegexp = /^[0-9]+$/;
class ZipCodeValidator {
    isAcceptable(s: string) {
        return s.length === 5 && numberRegexp.test(s);
    }
}
export = ZipCodeValidator;
Test.ts
import zip = require("./ZipCodeValidator");
 
// Some samples to try
let strings = ["Hello", "98052", "101"];
 
// Validators to use
let validator = new zip();
 
// Show whether each string passed each validator
strings.forEach(s => {
  console.log(`"${ s }" - ${ validator.isAcceptable(s) ? "matches" : "does not match" }`);
});

Code Generation for Modules

컴파일하는 동안 지정된 모듈 타겟에 따라 컴파일러는 Node.js (CommonJS), require.js (AMD), UMD, SystemJS 또는 ECMAScript 2015 네이티브 모듈 (ES6) 모듈로드 시스템에 적합한 코드를 생성합니다. 생성 된 코드에서 define, requireregister 호출에 대한 자세한 내용은 각 모듈 로더에 대한 설명서를 참조하십시오.

이 간단한 예제는 가져 오기 및 내보내기 중에 사용 된 이름이 모듈 로딩 코드로 어떻게 변환되는지 보여줍니다.

SimpleModule.ts
import m = require("mod")
export let t = m.something + 1;
AMD/RequireJS SimpleModule.js
define(["require", "exports", "./mod"], function (require, exports, mod_1) {
  exports.t = mod_1.something + 1;
});
CommonJS / Node SimpleModule.js
var mod_1 = require("./mod");
exports.t = mod_1.something + 1;
UMD SimpleModule.js
(function (factory) {
    if (typeof module === "object" && typeof module.exports === "object") {
        var v = factory(require, exports); if (v !== undefined) module.exports = v;
    }
    else if (typeof define === "function" && define.amd) {
        define(["require", "exports", "./mod"], factory);
    }
})(function (require, exports) {
    var mod_1 = require("./mod");
    exports.t = mod_1.something + 1;
});
System SimpleModule.js
System.register(["./mod"], function(exports_1) {
    var mod_1;
    var t;
    return {
        setters:[
            function (mod_1_1) {
                mod_1 = mod_1_1;
            }],
        execute: function() {
            exports_1("t", t = mod_1.something + 1);
        }
    }
});
Native ECMAScript 2015 modules SimpleModule.js
import { something } from "./mod";
export var t = something + 1;

Simple Example

아래에서는 앞의 예제에서 사용 된 유효성 검사기 구현을 통합하여 각 모듈에서 하나의 명명 된 내보내기 만 내보내도록했습니다.

컴파일하려면 명령 줄에 모듈 대상을 지정해야합니다. Node.js의 경우 –module commonjs를 사용하십시오. require.js에 대해 –module amd를 사용하십시오.

예 :

tsc --module commonjs Test.ts

컴파일되면 각 모듈은 별도의 .js 파일이됩니다. 참조 태그와 마찬가지로 컴파일러는 import 문을 따라 종속 파일을 컴파일합니다.

Validation.ts
export interface StringValidator {
    isAcceptable(s: string): boolean;
}
LettersOnlyValidator.ts
import { StringValidator } from "./Validation";
 
const lettersRegexp = /^[A-Za-z]+$/;
 
export class LettersOnlyValidator implements StringValidator {
    isAcceptable(s: string) {
        return lettersRegexp.test(s);
    }
}
ZipCodeValidator.ts
import { StringValidator } from "./Validation";
 
const numberRegexp = /^[0-9]+$/;
 
export class ZipCodeValidator implements StringValidator {
    isAcceptable(s: string) {
        return s.length === 5 && numberRegexp.test(s);
    }
}
Test.ts
import { StringValidator } from "./Validation";
import { ZipCodeValidator } from "./ZipCodeValidator";
import { LettersOnlyValidator } from "./LettersOnlyValidator";
 
// Some samples to try
let strings = ["Hello", "98052", "101"];
 
// Validators to use
let validators: { [s: string]: StringValidator; } = {};
validators["ZIP code"] = new ZipCodeValidator();
validators["Letters only"] = new LettersOnlyValidator();
 
// Show whether each string passed each validator
strings.forEach(s => {
    for (let name in validators) {
        console.log(`"${ s }" - ${ validators[name].isAcceptable(s) ? "matches" : "does not match" } ${ name }`);
    }
});

Optional Module Loading and Other Advanced Loading Scenarios

경우에 따라서 어떤 조건에서만 모듈을 로드를 원할 수 있습니다. TypeScript에서는 타입 안전성을 유지하면서 모듈 로더를 직접 호출 할 수 있도록 다음과 같은 고급로드 시나리오를 구현하기 위해 아래에 표시된 패턴을 사용할 수 있습니다.

컴파일러는 각 모듈이 방출된(emitted) JavaScript에서 사용되는지 여부를 감지합니다. 모듈 식별자가 타입 주석의 일부로 만 사용되고 식이 아닌 경우에는 해당 모듈에 대한 호출이 필요하지 않습니다. 사용하지 않는 참조를 제거하면 좋은 성능 최적화를 얻을 수 있으며 해당 모듈을 선택적으로 로드 할 수 있습니다.

이 패턴의 핵심 아이디어는 import id = require(“…”) 문을 사용하면 모듈에 의해 노출 된 유형에 액세스 할 수 있다는 것입니다. 모듈 로더는 아래의 if 블록 에서처럼 동적으로 호출됩니다 (require를 통해). 이는 레퍼런스-엘리먼 지 최적화를 활용하므로 필요한 경우에만 모듈이로드됩니다. 이 패턴이 작동하려면 import를 통해 정의 된 기호가 타입 위치에서만 사용되어야합니다 (즉, 자바 스크립트로 전송되는 위치에 절대 사용되지 않음).

타입 안전성을 유지하기 위해 typeof 키워드를 사용할 수 있습니다. typeof 키워드를 타입 위치에서 사용하면 값 타입 (이 경우 모듈 타입)이 생성됩니다.

Dynamic Module Loading in Node.js
declare function require(moduleName: string): any;
 
import { ZipCodeValidator as Zip } from "./ZipCodeValidator";
 
if (needZipValidation) {
    let ZipCodeValidator: typeof Zip = require("./ZipCodeValidator");
    let validator = new ZipCodeValidator();
    if (validator.isAcceptable("...")) { /* ... */ }
}
Sample: Dynamic Module Loading in require.js
declare function require(moduleNames: string[], onLoad: (...args: any[]) => void): void;
 
import * as Zip from "./ZipCodeValidator";
 
if (needZipValidation) {
    require(["./ZipCodeValidator"], (ZipCodeValidator: typeof Zip) => {
        let validator = new ZipCodeValidator.ZipCodeValidator();
        if (validator.isAcceptable("...")) { /* ... */ }
    });
}
Sample: Dynamic Module Loading in System.js
declare const System: any;
 
import { ZipCodeValidator as Zip } from "./ZipCodeValidator";
 
if (needZipValidation) {
    System.import("./ZipCodeValidator").then((ZipCodeValidator: typeof Zip) => {
        var x = new ZipCodeValidator();
        if (x.isAcceptable("...")) { /* ... */ }
    });
}

Working with Other JavaScript Libraries

TypeScript로 작성되지 않은 라이브러리의 모양을 설명하려면 라이브러리가 노출하는 API를 선언해야합니다.

구현을 “ambient”으로 정의하지 않는 선언을 호출합니다. 일반적으로 .d.ts파일에 정의되어 있습니다. C/C ++에 익숙하다면이 파일을 .h 파일로 생각할 수 있습니다. 몇 가지 예를 살펴 보겠습니다.

주변 모듈(Ambient Modules)

Node.js에서 대부분의 작업은 하나 이상의 모듈을로드하여 수행됩니다. 최상위 수준의 내보내기 선언을 사용하여 각 모듈을 자체 .d.ts 파일로 정의 할 수 있지만 더 큰 .d.ts 파일로 작성하는 것이 더 편리합니다. 그렇게하기 위해, 우리는 앰비언트 네임 스페이스와 비슷한 구조를 사용하지만, module 키워드와 추후 가져올 수있는 모듈의 인용된 이름을 사용합니다.

예 :

node.d.ts(simplified excerpt)
declare module "url" {
    export interface Url {
        protocol?: string;
        hostname?: string;
        pathname?: string;
    }
 
    export function parse(urlStr: string, parseQueryString?, slashesDenoteHost?): Url;
}
 
declare module "path" {
    export function normalize(p: string): string;
    export function join(...paths: any[]): string;
    export var sep: string;
}

이제 /// <reference> node.d.ts참조할 수 있고 import url = require(“url”); 또는 import * as URL from “url”을 사용하여 모듈을 로드할 수 있다.

/// <reference path="node.d.ts"/>
import * as URL from "url";
let myUrl = URL.parse("http://www.typescriptlang.org");

Shorthand ambient modules

새 모듈을 사용하기 전에 선언을 작성하는 데 시간을 허비하지 않으려면 속기 선언을 사용하여 신속하게 시작할 수 있습니다.

declarations.d.ts
declare module "hot-new-module";

속성 모듈로부터의 모든 imports는 any타입을 가진다.

declarations.d.ts
import x, {y} from "hot-new-module";
x(y);

Wildcard module declarations

SystemJS 및 AMD와 같은 일부 모듈 로더는 JavaScript가 아닌 컨텐트를 가져올 수 있습니다. 이들은 일반적으로 특수 로딩 의미를 나타 내기 위해 접두어 나 접미사를 사용합니다. 이러한 경우를 다루기 위해 와일드 카드 모듈 선언을 사용할 수 있습니다.

declare module "*!text" {
  const content: string;
  export default content;
}
// Some do it the other way around.
declare module "json!*" {
  const value: any;
  export default value;
}

“*!text” 또는 “json!*”에 매치되는 것을 import.

import fileContent from "./xyz.txt!text";
import data from "json!http://example.com/data.json";
console.log(data, fileContent);

UMD modules

일부 라이브러리는 많은 모듈 로더 또는 모듈 로딩없이 사용되도록 설계되었습니다 (전역 변수). 이것들을 UMD 모듈이라고합니다. 이러한 라이브러리는 가져오기 또는 전역 변수를 통해 액세스 할 수 있습니다.

예 :

math-lib.d.ts
export function isPrime(x: number): boolean;
export as namespace mathLib;

그런 다음 라이브러리를 모듈 내에서 가져오기로 사용할 수 있습니다.

import { isPrime } from "math-lib";
isPrime(2);
mathLib.isPrime(2); // ERROR; can't use the global definition from inside a module

또한 전역 변수로 사용할 수도 있지만 스크립트 내부에서만 사용할 수 있습니다. (스크립트는 가져 오기 또는 내보내기가없는 파일입니다.)

mathLib.isPrime(2);

Guidance for structuring modules

Export as close to top-level as possible

수출하는 것을 사용할 때 모듈의 소비자는 가능한 한 마찰이 적어야합니다. 너무 많은 중첩 수준을 추가하는 것은 성가신 경향이 있으므로 사물을 구조화하려는 방법에 대해 신중히 생각하십시오.

모듈에서 네임 스페이스를 내보내는 것은 네스트 레이어를 너무 많이 추가하는 예입니다. 네임 스페이스가 언젠가는 사용하는 동안, 모듈을 사용할 때 여분의 수준의 간접 참조를 추가합니다. 이것은 사용자에게 고통스런 포인트가 될 수 있으며 일반적으로 불필요합니다.

내 보낸 클래스의 정적 메서드는 비슷한 문제가 있습니다. 클래스 자체는 중첩 레이어를 추가합니다. 표현이나 의도가 분명히 유용한 방식으로 증가하지 않는 한 단순히 도우미 함수를 내보내는 것을 고려하십시오.

단일 class 나 function 만 내보내는 경우에는 export default

“최상위 레벨 근처로 내보내기”가 모듈 사용자의 마찰을 줄이는 것처럼 기본 내보내기를 도입합니다. 모듈의 주요 목적이 하나의 특정 내보내기를 저장하는 것이면 기본 내보내기로 내보내기를 고려해야합니다. 이렇게하면 가져 오기를 사용하고 실제로 가져 오기를 조금 더 쉽게 사용할 수 있습니다.

예 :

MyClass.ts
export default class SomeType {
  constructor() { ... }
}
MyFunc.ts
export default function getThing() { return "thing"; }
Consumer.ts
import t from "./MyClass";
import f from "./MyFunc";
let x = new t();
console.log(f());

이것은 소비자를 위한 옵션입니다. 그들은 원하는대로 타입을 지정할 수 있으며 (이 경우 t), 개체를 찾기 위해 과도한 dotting 작업을 수행 할 필요가 없습니다.

여러 개체를 내보내는 경우 최상위 수준에 모두 배치하십시오.

MyThings.ts
export class SomeType { /* ... */ }
export function someFunc() { /* ... */ }

반대로 가져올 때 : 가져온 이름을 명시적으로 나열

Consumer.ts
import { SomeType, someFunc } from "./MyThings";
let x = new SomeType();
let y = someFunc();

많은 수의 항목을 가져 오는 경우 네임 스페이스 가져 오기 패턴을 사용하십시오.

MyLargeModule.ts
export class Dog { ... }
export class Cat { ... }
export class Tree { ... }
export class Flower { ... }
Consumer.ts
import * as myLargeModule from "./MyLargeModule.ts";
let x = new myLargeModule.Dog();

Re-export to extend

종종 모듈에서 기능을 확장해야합니다. 일반적인 JS 패턴은 JQuery 확장이 작동하는 것과 유사한 확장을 사용하여 원래 객체를 보강하는 것입니다. 앞서 언급했듯이 모듈은 전역 이름 공간 객체처럼 병합되지 않습니다. 권장되는 솔루션은 원래 개체를 변경하지 않고 새로운 기능을 제공하는 새 엔터티를 내보내는 것입니다.

Calculator.ts 모듈에 정의 된 간단한 계산기 구현을 고려하십시오. 또한 모듈은 입력 문자열 목록을 전달하고 끝에 결과를 작성하여 계산기 기능을 테스트하는 도우미 함수를 내 보냅니다.

Calculator.ts
export class Calculator {
    private current = 0;
    private memory = 0;
    private operator: string;
 
    protected processDigit(digit: string, currentValue: number) {
        if (digit >= "0" && digit <= "9") {
            return currentValue * 10 + (digit.charCodeAt(0) - "0".charCodeAt(0));
        }
    }
 
    protected processOperator(operator: string) {
        if (["+", "-", "*", "/"].indexOf(operator) >= 0) {
            return operator;
        }
    }
 
    protected evaluateOperator(operator: string, left: number, right: number): number {
        switch (this.operator) {
            case "+": return left + right;
            case "-": return left - right;
            case "*": return left * right;
            case "/": return left / right;
        }
    }
 
    private evaluate() {
        if (this.operator) {
            this.memory = this.evaluateOperator(this.operator, this.memory, this.current);
        }
        else {
            this.memory = this.current;
        }
        this.current = 0;
    }
 
    public handleChar(char: string) {
        if (char === "=") {
            this.evaluate();
            return;
        }
        else {
            let value = this.processDigit(char, this.current);
            if (value !== undefined) {
                this.current = value;
                return;
            }
            else {
                let value = this.processOperator(char);
                if (value !== undefined) {
                    this.evaluate();
                    this.operator = value;
                    return;
                }
            }
        }
        throw new Error(`Unsupported input: '${char}'`);
    }
 
    public getResult() {
        return this.memory;
    }
}
 
export function test(c: Calculator, input: string) {
    for (let i = 0; i < input.length; i++) {
        c.handleChar(input[i]);
    }
 
    console.log(`result of '${input}' is '${c.getResult()}'`);
}

다음은 노출된 test 함수를 사용하는 계산기의 간단한 테스트입니다.

TestCalculator.ts
import { Calculator, test } from "./Calculator";
 
let c = new Calculator();
test(c, "1+2*33/11="); // prints 9

이제 이것을 확장하여 10이 아닌 다른 수의 입력에 대한 지원을 추가하십시오. ProgrammerCalculator.ts를 만듭니다.

ProgrammerCalculator.ts
import { Calculator } from "./Calculator";
 
class ProgrammerCalculator extends Calculator {
    static digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];
 
    constructor(public base: number) {
        super();
        const maxBase = ProgrammerCalculator.digits.length;
        if (base <= 0 || base > maxBase) {
            throw new Error(`base has to be within 0 to ${maxBase} inclusive.`);
        }
    }
 
    protected processDigit(digit: string, currentValue: number) {
        if (ProgrammerCalculator.digits.indexOf(digit) >= 0) {
            return currentValue * this.base + ProgrammerCalculator.digits.indexOf(digit);
        }
    }
}
 
// Export the new extended calculator as Calculator
export { ProgrammerCalculator as Calculator };
 
// Also, export the helper function
export { test } from "./Calculator";

새로운 모듈 ProgrammerCalculator는 원래 Calculator 모듈과 유사한 API 모양을 내 보냅니다. 그러나 원래 모듈의 모든 오브젝트를 보강하지 않습니다. 다음은 우리의 ProgrammerCalculator 클래스에 대한 테스트입니다.

TestProgrammerCalculator.ts
import { Calculator, test } from "./ProgrammerCalculator";
 
let c = new Calculator(2);
test(c, "001+010="); // prints 3

모듈에서 namespace를 사용하지 마라 모듈 기반 조직으로 처음 이동하면 일반적으로 추가 네임 스페이스 계층에 내보내기를 래핑하는 경향이 있습니다. 모듈은 자체 범위를 가지며 내 보낸 선언만 모듈 외부에서 볼 수 있습니다. 이를 염두에두고, 네임스페이스는 모듈을 사용할 때 아주 작은 값을 제공합니다.

조직 측면에서는 네임스페이스가 논리적으로 관련된 개체와 유형을 전체 범위로 그룹화 할 때 편리합니다. 예를 들어 C#에서는 System.Collections의 모든 컬렉션 유형을 찾습니다. 유형을 계층 적 네임스페이스로 구성하여 이러한 유형의 사용자에게 적합한 “검색”환경을 제공합니다. 반면 모듈은 필연적으로 파일 시스템에 이미 존재합니다. 경로와 파일 이름으로 해결해야하므로 사용할 수있는 논리적 조직 체계가 있습니다. 목록 모듈이있는 /collections/generic/ 폴더를 가질 수 있습니다.

네임스페이스는 전역 범위에서 충돌 이름을 지정하지 않는 것이 중요합니다. 예를 들어, My.Application.Customer.AddForm 및 My.Application.Order.AddForm을 가질 수 있습니다. 이름은 같지만 이름 공간이 다른 두 가지 유형이 있습니다. 그러나 이것은 모듈의 문제가 아닙니다. 모듈 내에서 동일한 이름을 가진 두 개의 객체를 갖는 그럴듯한 이유는 없습니다. 소비 측면에서, 주어진 모듈의 소비자는 모듈을 참조하는 데 사용할 이름을 선택하게되므로 우발적인 이름 충돌이 불가능합니다.

모듈 및 네임스페이스에 대한 자세한 내용은 네임스페이스 및 모듈을 참조하십시오.

Red Flags

다음은 모두 모듈 구조화를위한 적색 플래그입니다. 이 중 하나라도 파일에 적용되는 경우 외부 모듈의 네임 스페이스를 시도하지 않는지 다시 확인하십시오.

  • 최상위 선언 만 export namespace Foo {…} (Foo를 제거하고 모든 것을 'up' 레벨)
  • 동일한 export namespace Foo {최상위 수준에있는 여러 파일 (이 파일이 하나의 Foo에 결합되지 않을 것이라고 생각하지 마십시오!)
typescript/module.txt · 마지막으로 수정됨: 2025/04/15 10:05 저자 127.0.0.1