typescript 핸드북 학습내용 정리
https://typescript-kr.github.io/pages/the-handbook.html
모듈
JS에서 모듈 로더는 CommonJS랑 RequireJS가 있었음.
TS와 JS는 ECMA 2015 이후의 import, export를 활용함.
Export
선언 Export 하기
모든 선언(변수, 함수, 클래스, 타입 별칭, 인터페이스)를 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 문
다른 사용자를 위해 이름을 바꿔서 내보내자
class ZipCodeValidator implements StringValidator {
isAcceptable(s: string) {
return s.length === 5 && numberRegexp.test(s);
}
}
export { ZipCodeValidator };
export { ZipCodeValidator as mainValidator };
Re-export 하기
선택적으로 하나의 모듈은 하나 혹은 여러개의 모듈을 감쌀 수 있고, export * from “module” 구문을 사용해 export 하는 것을 모두 결합할 수 있음.
export * from "./StringValidator"; // 'StringValidator' 인터페이스를 내보냄
export * from "./ZipCodeValidator"; // 'ZipCodeValidator' 와 const 'numberRegexp' 클래스를 내보냄
export * from "./ParseIntBasedZipCodeValidator";
// 'ParseIntBasedZipCodeValidator' 클래스를 내보냄
// 'ZipCodeValidator.ts' 모듈 에 있는
// 'ZipCodeValidator' 클래스를
// 'RegExpBasedZipCodeValidator' 라는 별칭으로 다시 내보냄
라이브러리 배포할때 씀
Import
단일 export를 import 하기
import { ZipCodeValidator } from "./ZipCodeValidator";
let myValidator = new ZipCodeValidator();
이름 수정 가능
import { ZipCodeValidator as ZCV } from "./ZipCodeValidator";
let myValidator = new ZCV();
전체 모듈을 단일 변수로 import해서, 모듈 exports 접근에 사용하기
import * as validator from "./ZipCodeValidator";
let myValidator = new validator.ZipCodeValidator();
부수효과만을 위해 모듈 import 하기
권장되지 않음. css의 경우 이렇게 많이 쓰고 있습니다.
import "./my-module.js"
타입 import 하기
// 동일한 import를 재사용하기
import {APIResponseType} from "./api";
// 명시적으로 import type을 사용하기
import type {APIResponseType} from "./api";
// 함수나 상수, 변수와 섞였을때
import { Fns, Cons, Lets, type Types} from "./api";
Default exports
기본 export
jQuery의 경우
// JQuery.d.ts
declare let $: JQuery;
export default $;
// App.ts
import $ from "jquery";
$("button.continue").html( "Next Step..." );
클래스 및 함수는 default export로 직접 작성됨
export default class 어쩌고 {}
export default function 저쩌고() {}
// 아래 같은 상수, 변수, 화살표 함수는 안됨
export default const a = '1';
export default let b = '2';
export default const test = () => {
console.log('test');
}
값도 가능
export default "123";
x로 모두 export 하기
export * as utilities from "./utilities";
import { utilities } from "./index";
export =와 import = require()
기존의 CommonJS와 AMD 워크플로우를 모델링 하기 위해 export =를 지원
앞으로도 쭉 안 쓸꺼라 넘어감
모듈을 위한 코드 생성
2015 네이티브만 쓸꺼라 생략
간단한 예제
패스
선택적 모듈 로딩과 기타 고급 로딩 시나리오
- 특정조건에서만 모듈을 로드하도록 만들 수 있음
declare function require(moduleName: string): any;
//타입으로 임포트 안하면 오류남
import type { ZipCodeValidator as Zip } from './ZipCodeValidator';
let needZipValidation = true;
if (needZipValidation) {
let ZipCodeValidator: typeof Zip = require('./ZipCodeValidator');
let validator = new ZipCodeValidator();
if (validator.isAcceptable('...')) {
/* ... */
}
}
다른 Javascript 라이브러리와 함께 사용하기
구현을 정의하지 않은 선언을 "ambient"라고 부름. 일반적으로 d.ts에 정의되어있음.
Ambient 모듈
각 모듈을 d.ts로 정의할 수 있지만 더 큰 하나의 d.ts가 편함(next나 sveltekit처럼)
// node.d.ts
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;
}
아래처럼 씀. next나 sveltekit은 reference 설정 자동으로 해줌
/// <reference path="node.d.ts"/>
import * as URL from "url";
let myUrl = URL.parse("http://www.typescriptlang.org");
속기 ambient 모듈
declare module "hot-new-module";
위처럼 선언하면 전부다 any 타입을 가짐
와일드카드 모듈 선언
SystemJs, AMD 같은거 안 쓸꺼라 패스
UMD 모듈
일부 라이브러리는 많은 모듈 로더에서 사용되거나, 모듈 로딩 없이 사용되도록 설계되어있음. 이를 UMD 모듈이라 함.
// math-lib.d.ts
export function isPrime(x: number): boolean;
export as namespace mathLib;
// 라이브러리는 모듈 내에서 import로 사용할 수 있습니다:
import { isPrime } from "math-lib";
isPrime(2);
mathLib.isPrime(2); // 오류: 모듈 내부에서 전역 정의를 사용할 수 없습니다.
// 전역 변수로도 사용할 수 있지만, 스크립트 내에서만 사용할 수 있습니다. (스크립트는 imports나 exports가 없는 파일입니다.)
mathLib.isPrime(2);
모듈 구조화에 대한 지침
가능한 최상위 레벨에 가깝게
가능한 중첩이 없도록 설계하라
- 단일 class나 function을 export 할 경우 export default를 쓸것
- 여러 객체를 export하는 경우, 최상위 레벨에 두자
export class SomeType { /* ... */ }
export function someFunc() { /* ... */ }
- import 한 이름을 명시적으로 나열
import { SomeType, someFunc } from "./MyThings";
let x = new SomeType();
let y = someFunc();
- 많은 것을 import 하는 경우, 네임스페이스 import 패턴을 사용할 것
// 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하기
기존의 객체를 변경하지 않고 새로운 기능을 제공하는 개체를 export 해라
모듈에서 네임스페이스를 사용하지 말 것
네임스페이스는 전역 스코프에서 네이밍 충돌을 피하기 위해 사용됨.
허나 모듈 내에서 두개의 객체가 같은 이름을 가질 이유는 없음
위험신호
- 오직 최상위-레벨 선언만 export namespace Foo { … }인 파일 (Foo를 제거하고 모든 것을 ‘상위’ 레벨로 이동하세요)
- 최상위-레벨 위치에 동일한 export namespace Foo {를 가진 여러 파일 (하나의 Foo로 결합될 거라 생각하지 마세요!)
'공부공부 > TS' 카테고리의 다른 글
[typescript 핸드북] 11. 네임스페이스 (1) | 2024.02.19 |
---|---|
[typescript 핸드북] 10. 모듈 해석 (0) | 2024.02.19 |
[typescript 핸드북] 08. 유틸리티 타입 (0) | 2024.02.19 |
[typescript 핸드북] 07. 제네릭 (0) | 2024.02.19 |
[typescript 핸드북] 06. 열거형 (0) | 2024.02.19 |