문서의 선택한 두 판 사이의 차이를 보여줍니다.
| 양쪽 이전 판이전 판다음 판 | 이전 판 | ||
| typescript:module [2019/07/30 06:16] – [주변 모듈(Ambient Modules)] taekgu | typescript:module [2025/04/15 10:05] (현재) – 바깥 편집 127.0.0.1 | ||
|---|---|---|---|
| 줄 391: | 줄 391: | ||
| </ | </ | ||
| - | 이제 | + | 이제 |
| + | <code javascript> | ||
| + | /// < | ||
| + | import * as URL from " | ||
| + | let myUrl = URL.parse(" | ||
| + | </ | ||
| + | |||
| + | ==== Shorthand ambient modules ==== | ||
| + | 새 모듈을 사용하기 전에 선언을 작성하는 데 시간을 허비하지 않으려면 속기 선언을 사용하여 신속하게 시작할 수 있습니다. | ||
| + | |||
| + | <code javascript declarations.d.ts> | ||
| + | declare module " | ||
| + | </ | ||
| + | |||
| + | 속성 모듈로부터의 모든 imports는 '' | ||
| + | |||
| + | <code javascript declarations.d.ts> | ||
| + | import x, {y} from " | ||
| + | x(y); | ||
| + | </ | ||
| + | |||
| + | ==== Wildcard module declarations ==== | ||
| + | SystemJS 및 AMD와 같은 일부 모듈 로더는 JavaScript가 아닌 컨텐트를 가져올 수 있습니다. 이들은 일반적으로 특수 로딩 의미를 나타 내기 위해 접두어 나 접미사를 사용합니다. 이러한 경우를 다루기 위해 와일드 카드 모듈 선언을 사용할 수 있습니다. | ||
| + | |||
| + | <code javascript> | ||
| + | declare module " | ||
| + | const content: string; | ||
| + | export default content; | ||
| + | } | ||
| + | // Some do it the other way around. | ||
| + | declare module " | ||
| + | const value: any; | ||
| + | export default value; | ||
| + | } | ||
| + | </ | ||
| + | ''" | ||
| + | |||
| + | <code javascript> | ||
| + | import fileContent from " | ||
| + | import data from " | ||
| + | console.log(data, | ||
| + | </ | ||
| + | |||
| + | ==== UMD modules ==== | ||
| + | 일부 라이브러리는 많은 모듈 로더 또는 모듈 로딩없이 사용되도록 설계되었습니다 (전역 변수). 이것들을 UMD 모듈이라고합니다. 이러한 라이브러리는 가져오기 또는 전역 변수를 통해 액세스 할 수 있습니다. | ||
| + | |||
| + | 예 : | ||
| + | <code javascript math-lib.d.ts> | ||
| + | export function isPrime(x: number): boolean; | ||
| + | export as namespace mathLib; | ||
| + | </ | ||
| + | |||
| + | 그런 다음 라이브러리를 모듈 내에서 가져오기로 사용할 수 있습니다. | ||
| + | |||
| + | <code javascript> | ||
| + | import { isPrime } from " | ||
| + | isPrime(2); | ||
| + | mathLib.isPrime(2); | ||
| + | </ | ||
| + | |||
| + | 또한 전역 변수로 사용할 수도 있지만 스크립트 내부에서만 사용할 수 있습니다. (스크립트는 가져 오기 또는 내보내기가없는 파일입니다.) | ||
| + | |||
| + | <code javascript> | ||
| + | |||
| + | ===== Guidance for structuring modules ===== | ||
| + | ==== Export as close to top-level as possible ==== | ||
| + | 수출하는 것을 사용할 때 모듈의 소비자는 가능한 한 마찰이 적어야합니다. 너무 많은 중첩 수준을 추가하는 것은 성가신 경향이 있으므로 사물을 구조화하려는 방법에 대해 신중히 생각하십시오. | ||
| + | |||
| + | 모듈에서 네임 스페이스를 내보내는 것은 네스트 레이어를 너무 많이 추가하는 예입니다. 네임 스페이스가 언젠가는 사용하는 동안, 모듈을 사용할 때 여분의 수준의 간접 참조를 추가합니다. 이것은 사용자에게 고통스런 포인트가 될 수 있으며 일반적으로 불필요합니다. | ||
| + | |||
| + | 내 보낸 클래스의 정적 메서드는 비슷한 문제가 있습니다. 클래스 자체는 중첩 레이어를 추가합니다. 표현이나 의도가 분명히 유용한 방식으로 증가하지 않는 한 단순히 도우미 함수를 내보내는 것을 고려하십시오. | ||
| + | |||
| + | '' | ||
| + | |||
| + | " | ||
| + | |||
| + | 예 : | ||
| + | <code javascript MyClass.ts> | ||
| + | export default class SomeType { | ||
| + | constructor() { ... } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | <code javascript MyFunc.ts> | ||
| + | export default function getThing() { return " | ||
| + | </ | ||
| + | |||
| + | <code javascript Consumer.ts> | ||
| + | import t from " | ||
| + | import f from " | ||
| + | let x = new t(); | ||
| + | console.log(f()); | ||
| + | </ | ||
| + | |||
| + | 이것은 소비자를 위한 옵션입니다. 그들은 원하는대로 타입을 지정할 수 있으며 (이 경우 t), 개체를 찾기 위해 과도한 dotting 작업을 수행 할 필요가 없습니다. | ||
| + | |||
| + | **'' | ||
| + | <code javascript MyThings.ts> | ||
| + | export class SomeType { /* ... */ } | ||
| + | export function someFunc() { /* ... */ } | ||
| + | </ | ||
| + | |||
| + | 반대로 가져올 때 : | ||
| + | '' | ||
| + | <code javascript Consumer.ts> | ||
| + | import { SomeType, someFunc } from " | ||
| + | let x = new SomeType(); | ||
| + | let y = someFunc(); | ||
| + | </ | ||
| + | |||
| + | '' | ||
| + | <code javascript MyLargeModule.ts> | ||
| + | export class Dog { ... } | ||
| + | export class Cat { ... } | ||
| + | export class Tree { ... } | ||
| + | export class Flower { ... } | ||
| + | </ | ||
| + | |||
| + | <code javascript Consumer.ts> | ||
| + | import * as myLargeModule from " | ||
| + | let x = new myLargeModule.Dog(); | ||
| + | </ | ||
| + | |||
| + | ==== Re-export to extend ==== | ||
| + | 종종 모듈에서 기능을 확장해야합니다. 일반적인 JS 패턴은 JQuery 확장이 작동하는 것과 유사한 확장을 사용하여 원래 객체를 보강하는 것입니다. 앞서 언급했듯이 모듈은 전역 이름 공간 객체처럼 병합되지 않습니다. 권장되는 솔루션은 원래 개체를 변경하지 않고 새로운 기능을 제공하는 새 엔터티를 내보내는 것입니다. | ||
| + | |||
| + | Calculator.ts 모듈에 정의 된 간단한 계산기 구현을 고려하십시오. 또한 모듈은 입력 문자열 목록을 전달하고 끝에 결과를 작성하여 계산기 기능을 테스트하는 도우미 함수를 내 보냅니다. | ||
| + | |||
| + | <code javascript Calculator.ts> | ||
| + | export class Calculator { | ||
| + | private current = 0; | ||
| + | private memory = 0; | ||
| + | private operator: string; | ||
| + | |||
| + | protected processDigit(digit: | ||
| + | if (digit >= " | ||
| + | return currentValue * 10 + (digit.charCodeAt(0) - " | ||
| + | } | ||
| + | } | ||
| + | |||
| + | protected processOperator(operator: | ||
| + | if ([" | ||
| + | return operator; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | protected evaluateOperator(operator: | ||
| + | switch (this.operator) { | ||
| + | case " | ||
| + | case " | ||
| + | case " | ||
| + | case "/": | ||
| + | } | ||
| + | } | ||
| + | |||
| + | private evaluate() { | ||
| + | if (this.operator) { | ||
| + | this.memory = this.evaluateOperator(this.operator, | ||
| + | } | ||
| + | else { | ||
| + | this.memory = this.current; | ||
| + | } | ||
| + | this.current = 0; | ||
| + | } | ||
| + | |||
| + | public handleChar(char: | ||
| + | if (char === " | ||
| + | this.evaluate(); | ||
| + | return; | ||
| + | } | ||
| + | else { | ||
| + | let value = this.processDigit(char, | ||
| + | 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: ' | ||
| + | } | ||
| + | |||
| + | public getResult() { | ||
| + | return this.memory; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | export function test(c: Calculator, input: string) { | ||
| + | for (let i = 0; i < input.length; | ||
| + | c.handleChar(input[i]); | ||
| + | } | ||
| + | |||
| + | console.log(`result of ' | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | 다음은 노출된 '' | ||
| + | |||
| + | <code javascript TestCalculator.ts> | ||
| + | import { Calculator, test } from " | ||
| + | |||
| + | let c = new Calculator(); | ||
| + | test(c, " | ||
| + | </ | ||
| + | |||
| + | 이제 이것을 확장하여 10이 아닌 다른 수의 입력에 대한 지원을 추가하십시오. ProgrammerCalculator.ts를 만듭니다. | ||
| + | |||
| + | <code javascript ProgrammerCalculator.ts> | ||
| + | import { Calculator } from " | ||
| + | |||
| + | class ProgrammerCalculator extends Calculator { | ||
| + | static digits = [" | ||
| + | |||
| + | 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: | ||
| + | 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 " | ||
| + | </ | ||
| + | |||
| + | 새로운 모듈 ProgrammerCalculator는 원래 Calculator 모듈과 유사한 API 모양을 내 보냅니다. 그러나 원래 모듈의 모든 오브젝트를 보강하지 않습니다. 다음은 우리의 ProgrammerCalculator 클래스에 대한 테스트입니다. | ||
| + | |||
| + | <code javascript TestProgrammerCalculator.ts> | ||
| + | import { Calculator, test } from " | ||
| + | |||
| + | let c = new Calculator(2); | ||
| + | test(c, " | ||
| + | </ | ||
| + | |||
| + | ** 모듈에서 namespace를 사용하지 마라 ** | ||
| + | 모듈 기반 조직으로 처음 이동하면 일반적으로 추가 네임 스페이스 계층에 내보내기를 래핑하는 경향이 있습니다. 모듈은 자체 범위를 가지며 내 보낸 선언만 모듈 외부에서 볼 수 있습니다. 이를 염두에두고, | ||
| + | |||
| + | 조직 측면에서는 네임스페이스가 논리적으로 관련된 개체와 유형을 전체 범위로 그룹화 할 때 편리합니다. 예를 들어 C#에서는 System.Collections의 모든 컬렉션 유형을 찾습니다. 유형을 계층 적 네임스페이스로 구성하여 이러한 유형의 사용자에게 적합한 " | ||
| + | |||
| + | 네임스페이스는 전역 범위에서 충돌 이름을 지정하지 않는 것이 중요합니다. 예를 들어, My.Application.Customer.AddForm 및 My.Application.Order.AddForm을 가질 수 있습니다. 이름은 같지만 이름 공간이 다른 두 가지 유형이 있습니다. 그러나 이것은 모듈의 문제가 아닙니다. 모듈 내에서 동일한 이름을 가진 두 개의 객체를 갖는 그럴듯한 이유는 없습니다. 소비 측면에서, | ||
| + | |||
| + | >모듈 및 네임스페이스에 대한 자세한 내용은 네임스페이스 및 모듈을 참조하십시오. | ||
| + | |||
| + | ===== Red Flags ===== | ||
| + | 다음은 모두 모듈 구조화를위한 적색 플래그입니다. 이 중 하나라도 파일에 적용되는 경우 외부 모듈의 네임 스페이스를 시도하지 않는지 다시 확인하십시오. | ||
| + | * 최상위 선언 만 '' | ||
| + | * 동일한 '' | ||