타입스크립에서 모듈은 크게 두가지로 나누어 지는데
Internal Module ( 내부 모듈 )
External Module ( 외부 모듈 )
두 모듈의 가장큰 차이점의 의존성에 있다
다른 모듈 로더에 의존하지 않고
Typescript를 컴파일할때 이름이 명명된 Javascript 오브젝트를 생성함으로써
모듈화를 진행한다
namespace를 생성한다
Common.js/ Require.js/ ES6 Module 같은 Module - Loader에 의존성을 가진다
node의 경우는 namespace 보다는 module이 권고 사항이다
typescript를 컴파일러에게 특정한 변수가 있다고 선언하는 것으로
주로 전역변수, .d.ts 파일을 만들때 사용한다
1번의 경우는 외부모듈을 정의하는 방법 , 2번은 내부 모듈을 정의하는 방법
모듈명이 "" 로 감싸져 있다면 외부 모듈에 대한 정의이다
두가지 모두 선언을 하는 방식으로
차이점이 있다면 선언병합을 할수 있는지, 없는지에 있다
interface phoneNumber {
inputString?: string;
}
interface phoneNumber {
inputNumber?: number;
}
type phone {
numb: number;
}
// Error
type phone {
str: number;
}
interface의 경우 선언 병합이 가능하지만
type의 경우는 선언병합이 불가능하다
결합
' | ' 기호를 사용하여 유니온 타입을 나타낸다
or과 비슷한느낌이다
만약 유저에게 자유롭게 핸드폰 번호를 받는다면
function phoneNumberInput(phoneNumber: string | number) {
if ( typeof(phoneNumber) === "string"){
console.log("stringType")
} else {
console.log("numberType")
}}
이런식으로 Union Type을 활용하여 parameter의 타입을 정해줄 수 있다
위에서와 마찬가지로 parameter의 타입에 유니온 타입을 적용했다면
interface를 사용하여 객체의 타입을 지정해 준 뒤에도 사용해 줄 수 있다
interface Bird {
fly(): void;
layEggs(): void;
}
interface Fish {
swim(): void;
layEggs(): void;
}
declare function getSmallPet(): Fish | Bird;
let pet = getSmallPet();
pet.layEggs();
// Error
pet.swim()
이렇게 유니온 타입을 사용하여 타입을 정의 할 수 있지만,
interface에 유니온 타입을 적용할 경우에는 확실한 경우가 아니라면
공통된 layEggs()의 타입만을 사용 가능하다
type NetworkLoadingState = {
state: "loading";
};
type NetworkFailedState = {
state: "failed";
code: number;
};
type NetworkSuccessState = {
state: "success";
response: {
title: string;
duration: number;
summary: string;
};
};
type NetworkState =
| NetworkLoadingState
| NetworkFailedState
| NetworkSuccessState;
function networkStatus(state: NetworkState): string {
// Error
state.code;
// switch 문으로 구분해서 사용 가능
switch (state.state) {
case "loading":
return "Downloading...";
case "failed":
return `Error ${state.code} downloading`;
case "success":
return `Downloaded ${state.response.title} - ${state.response.summary}`;
}
}
type을 지정해 줌과 동시에 state에 값을 부여한 경우
switch문을 사용하여 구분해서 사용할 수 있다
enumerate로 번호를 지정해 준다
enum Direction {
up,
down,
left,
right
}
Direction.up // 0
Direction.down // 1
Direction.left // 2
Direction.right // 3
Direction["0"] // "up"
Direction["1"] // "down"
Direction["2"] // "left"
Direction["3"] // "right
제네릭을 쓰는 가장큰 이유는 여러 상황에 대처하기 위해서인 것 같다
여러 상황을 대처한다는 건 어떤 타입이 들어올지 모르는 상황이거나
정해지지 않은 상황에서 사용한다는 것이고, 이런 상황에서 generic을 사용하게 되면
간단하게 해결이 된다
제네릭을 생성하는 시점에서 타입을 지정해주고, 다양한 타입을 사용하게 해준다
가장 많이 사용하는 타입변수인 T는 type의 약자이기 때문에 사용한다
T를 사용하여, 함수를 생성할때 타입을 생성해주고
매개변수로 "string"을 받게 되면 T라는 타입변수에 저장이되고
사용하게 된다
아무것도 리턴하지 않는 void로 타입을 지정해주고
보게되면 T에 void가 담겨 있는걸 확인 할 수 있다
생성자? 라는 말이 좀 어울리는 것 같다