TypeScript 의 타입 별칭(Type alias)
이번에 다루어볼 내용은, 타입 별칭(Type alias)라는 것이다. 타입 별칭을 이용하면, 마치 변수를 통해 값을 저장하는 것 처럼 특정 타입을 저장하고 하용할 수 있다.
타입 별칭(type alias)
1
2
type A = string;
const str: A = 'hello';
지금은 간단한 에시로, A라는 새 타입을 정하고 string 타입으로 지정한 에시다. 이제부터, string 을 지정할 땐 string 대신 A 라고 타이핑해줘도 무방하다.
이렇게 타입 별칭을 설정할 때는 첫 글자를 대문자로 지정하는게 컨벤션이라고 한다. 사실, 타입 추론을 이용하면 되는 상황이라 좋은 예시는 아니다.
조금 더 좋은 예시를 보자.
1
2
3
4
const func1: (value: number, unit: string) => string = (value, unit) => value + unit;
const ValueWithUnit = (value: number, unit: string) => string;
const func2: ValueWithUnit = (value, unit) => value + unit;
함수의 타입을 지정할 때, func1
처럼 하게 되면 가독성이 좋지 않다. 그래서 ValueWithUnit
타입을 지정해, 함수의 타입을 미리 정하고 이를 func2
함수에 타이핑해준 것이다.
물론, 객체나 배열을 타이핑할 때도 이용할 수 있는데 이때는 interface
라는 것을 자주 사용한다.
인터페이스(interface)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
interface Person {
name: string,
age: number,
married: boolean
}
const person2: Person = {
name: 'k',
age: 1000,
married: true
}
const person3: Person = {
name: 'o',
age: 1,
married: false
}
이런 식으로 활용이 가능하다. 타입 별칭과 유사하게 첫 글자를 대문자로 설정하는 것이 컨벤션이다.
이렇게만 보면, 타입 별칭과 다를 것이 없어보이는데 사실 몇 가지 기능이 더 있으니 살펴보도록 하자.
1
2
3
4
5
6
7
8
9
10
interface Func {
(x: number, y: number): number,
}
const add : Func = (x, y) => x + y;
interface Arr {
length: number,
[key: number]: string,
}
인터페이스로 함수와 배열을 타이핑해준 예시다. 함수의 경우는 특별할 것은 없지만, 배열을 보면 조금 독특한 표기가 있다.
[key: number]
라는 표기가 있는데, 이를 인덱스 시그니처 라고 한다. 이 표기가 의미하는 것은 다음과 같다.
Arr 인터페이스를 가질 경우, length 를 제외한 다른 모든 키는 number 타입이고 그 짝(할당한 데이터)은 string 타입 이라는 것이다.
인터페이스 선언은 합칠 수 있다
인터페이스의 다른 특징은 서로 합칠 수 있다는 것이다.
1
2
3
4
5
6
7
8
9
10
11
12
interface Merge {
one: string
}
interface Merge {
two: number,
}
const example: Merge = {
one:'1',
two: 2,
}
이렇게 선언이 가능하다. 같은 이름으로 여러 번 선언할 수 있고, 이 인터페이스들은 자동으로 합쳐진다.
이런 동작을 선언 병합(delclaration merging)
이라고 부른다. 이 선언 병합은 확장하기 편하지만, 언제나 이럴 땐 의도하지 않은 결과가 생기기 마련이다.
서로 병합이 되어도 괜찮다면 모르겠지만, 서로 다른 타입을 지정하는 인터페이스가 같은 이름을 가지는 경우는 문제가 될 수 있다.
1
2
3
4
5
6
7
8
interface Merge {
one: string;
}
interface Merge {
one: number;
another: string;
}
물론, 같은 속성 키에 대해 다른 타입이 지정되어있다면 오류가 발생하긴 하지만 첫 번째 Merge 인터페이스를 사용하는 것은 another 라는 키가 없을 텐데, 병합 때문에 혼란이 생길 수 있다. 그래서 네임스페이스(namespace) 가 존재한다.
네임스페이스(namespace)
1
2
3
4
5
6
7
8
9
10
11
12
namespace Example {
export interface Inner {
test: string;
}
export type test2: number;
}
const ex1: Example.Inner = {
test: 'hello',
}
const ex2: Example.test2 = 1;
이렇게 네임스페이스를 선언하고 나면, 내부에서 사용할 타입 / 인터페이스를 반드시 export
해야한다.
그리고, 네임스페이스도 중첩이 가능하며 이름이 같은 네임스페이스의 경우에도 병합이 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
namespace Example {
export interface Inner {
test: string;
}
export type test2: number;
}
namespace Example {
export type test3: string;
}
namespace Outer {
export namespace Innter {
export interface Inner {
test: string;
}
export type test2: number;
}
}
네임스페이스를 중첩할 경우, 내부 네임스페이스는 반드시 export 를 해야 접근이 가능해지니 잊지 말자.