티스토리 뷰

do/typescript

typescript 3

dooo.park 2019. 4. 12. 16:24

제너릭(generic)

여러 타입에 대해 동일한 규칙을 갖고 동작하는 타입 정의할 수 있다.

해당 함수를 정의할 때는 알 수 없고 사용할 때에만 알 수 있는 타입

 

타입 변수

함수를 호출하는 시점이 되어야만 알 수 있는 값을 함수 내부에서 사용하기 위해서는 그 값을 담아둘 매개변수가 필요하다.

마찬가지로, 요소를 사용하는 시점에서만 알 수 있는 타입을 담아두기 위해서는 타입 변수(type variable)가 필요하다.

타입 변수와 타입의 관계는 매개변수와 인자 값의 관계와 비슷하다.

 

타입 변수와 제너릭의 핵심은 여러 타입에 대해 동작하는 요소를 정의하되,

해당 요소를 사용할 때가 되어야 알 수 있는 타입 정보를 정의에 사용하는 것이다. 

 

 

함수

제너릭

정의 시점

매개변수

a: number

타입 변수

<T>

정의 예시

function (a: number) {

...

}

type MyArray<T> = T[]

사용 시

실제 값 (3, 42 등) 사용

실제 타입(number, string 등) 사용

사용 예시

a(3); a(42);

type MyNumberArray = MyArray<number>

타입 변수는 부등호< >로 정의한다.

정의한 타입 변수를 요소의 타입 정의 (예를 들어 함수의 인자 및 반환 타입)에 사용할 수 있다.

부등호 기호 안에 정의된 타입 변수의 실제 타입은 실제 값이 넘어오는 시점에 결정된다.

컨벤션 상 타입스크립트의 타입 변수는 대문자로 시작하며 PascalCase 명명법을 사용한다.

● 카멜 표기법 
"camelCase" 
각 단어의 첫문자를 대문자로 표기하고 붙여쓰되, 맨처음 문자는 소문자로 표기함 
띄어쓰기 대신 대문자로 단어를 구분하는 표기 방식 
예시: backgroundColor, typeName, iPhone 


● 파스칼 표기법 
"PascalCase" 
첫 단어를 대문자로 시작하는 표기법 
예시: BackgroundColor, TypeName, PowerPoint

 

제너릭 함수

일반적으로는 다음과 같은 꼴이 된다. 이 때 인자 타입과 반환 타입을 표현할 때 타입 변수를 사용할 수 있다.

function 함수명<타입 변수>(인자 타입): 반환 타입 {

/* 함수 본문 */

}

함수를 호출 할 때에는 정의에서 매개변수가 있던 자리에 인자를 넣어준다.

마찬가지로, 제너릭 함수를 호출할 때에는 정의에서 타입 변수가 있던 자리에 타입 인자를 넣어준다.

const languages: string[] = ['TypeScript', 'JavaScript'];

const language = getFirstElem<string>(languages); // 이 때 language의 타입은 문자열

예시

임의의 타입 T에 대해, getFirstElem은 T 타입 값의 배열 arr를 인자로 받아 T 타입 값을 반환하는 함수다.

function getFirstElem<T>(arr: T[]): T {

/* 함수 본문 */

}

제너릭 타입 별칭

타입 별칭 정의에도 제너릭을 사용할 수 있다. 이 때 타입 변수 정의는 별칭 이름 다음에 붙여 쓴다.

type MyArray<T> = T[];

const drinks: MyArray<string> = ['Coffee', 'Milk', 'Beer'];

유니온(union)

어떤 타입이 가질 수 있는 경우의 수를 나열할 때 사용한다.

 

유니온 타입은 가능한 모든 타입을 파이프(|) 기호로 이어서 표현한다. 

“A 또는 B 타입일 수 있는 타입”을 A | B 로 쓰는 식이다. 

function square(value: number, returnString: boolean = false): string | number { 
  /* 본문 동일 */ 
} 
const stringOrNumber: string | number = square(randomNumber, randomBoolean);

타입 별칭 문법을 사용해 유니온 타입에 이름을 붙일 수 있다. 

type SquaredType = string | number; 
function square(value: number, returnOnString: boolean = false): SquaredType { 
  /* 본문 동일 */ 
} 

유니온 타입이 가질 수 있는 타입의 수는 여러 개 일 수 있다.

type Whatever = number | string | boolean;

여러 줄에 걸쳐 유니온 타입을 적을 때에는 보통 아래와 같이 정렬을 맞춘다.

type Fruits 
  = Apple 
  | Banana 
  | Cherry;

유니온 타입의 맨 앞에도 파이프를 쓰는 것이 허용된다. 

type Fruits = 
  | Apple 
  | Banana 
  | Cherry; 

인터섹션(intersection)

이미 존재하는 여러 타입을 모두 만족하는 타입을 표현한다.

 

문법
여러 타입을 앰퍼샌드(&) 기호로 이어서 인터섹션 타입을 나타낸다.

type BeerLovingProgrammer = Programmar & BeerLover;

A&B 타입의 값은 A 타입에도, B 타입에도 할당 가능해야 한다. 

A와 B 모두 객체 타입이라면 A&B 타입의 객체는 A와 B 타입 각각에 정의된 속성 모두를 가져야 한다.

 

이 때 어떤 값도 만족하지 않는 인터섹션 타입이 생길 수도 있다는 점에 주의해야 한다.

type Infeasible = string & number

문자열인 동시에 숫자인 값은 존재하지 않으므로, 위 Infeasible 타입은 실제로는 어떤 값도 가질 수 없다.


인터섹션 타입 역시 몇 개든 이어가며 정의할 수 있다.

type Awesome = Programmer & BeerLover & CatLover;

인터섹션 타입을 여러 줄에 걸쳐 적을 때 

type BeerLovingProgrammer
  = Programmer
  & BeerLover;
  
type BeerLovingProgrammer2 =
  & Programmer
  & BeerLover;

열거형(enum)

유한한 경우의 수를 갖는 값의 집합을 표현하기 위해 사용한다.

 

숫자 열거형(Numeric Enum)

number 타입 값에 기반한 열거형이다. 

 

열거형을 정의하며 멤버의 값을 초기화하지 않을 경우, 해당 멤버의 값은 0부터 순차적으로 증가하는 숫자 값을 갖는다.

enum Direction { 
  East, 
  West, 
  South, 
  North 
} 
enum ExplicitDirection { 
  East = 0, 
  West = 1, 
  South = 2, 
  North = 3 
}

열거형의 멤버에는 객체의 속성에 접근하는 것과 동일한 방식으로 접근할 수 있다. 

Enum의 모든 멤버는 Enum 타입을 갖는다.

const south: Direction = Direction.South; 
console.log(south); // 2 

0부터 시작되는 자동 초기화에 의존하는 대신, 각 멤버의 값을 직접 초기화 할 수 있다.

enum InitializedDirection { 
  East = 2, 
  West = 4, 
  South = 8, 
  North = 16 
} 

만약 초기화 되지 않은 멤버가 섞여있다면, 그 멤버의 값은 이전에 초기화된 멤버의 값으로부터 순차적으로 증가해서 결정된다.

enum InitializedDirection2 { 
  East = 3, 
  West /* 4 */, 
  South = 7, 
  North /* 8 */ 
} 

문자열 열거형(String Enum)

number 타입 값 대신 string 타입 값을 사용해서 멤버 값을 초기화하는 것도 가능하다. 

enum Direction { 
  East = 'EAST', 
  West = 'WEST', 
  South = 'SOUTH', 
  North = 'NORTH' 
}

문자열은 자동 증가 않으므로 모든 멤버는 명시적으로 초기화되어야 한다.

숫자 열거형과 달리, 문자열 열거형이 컴파일된 자바스크립트 코드에는 값 → 키 의 역방향 매핑(reverse mapping)이

존재하지 않는다.


상수 멤버와 계산된 멤버

상수멤버(constant member)

상수값으로 초기화 되는 멤버(숫자, 문자)

 

계산된 멤버(computed member)

런타임에 결정되는 값으로 초기화되는 멤버(함수)

값은 실제로 코드를 실행시켜봐야만 알 수 있으므로, 계산된 멤버 뒤에 오는 멤버는 반드시 초기화되어야 한다.

function getAnswer() { 
  return 42; 
} 
enum SpecialNumbers { 
  Answer = getAnswer(), 
  Mystery // error TS1061: Enum member must have initializer. 
} 


런타임에서의 열거형

타입스크립트 코드에서의 열거형 정의 및 접근은 아래와 같은 자바스크립트 코드로 컴파일 된다. 

enum Direction { 
  East, 
  West, 
  South, 
  North 
} 
const east: Direction = Direction.East; 

var Direction; 
(function (Direction) { 
    Direction[Direction["East"] = 0] = "East"; 
    Direction[Direction["West"] = 1] = "West"; 
    Direction[Direction["South"] = 2] = "South"; 
    Direction[Direction["North"] = 3] = "North"; 
})(Direction || (Direction = {})); 
var east = Direction.East; 

이 코드를 보면 두 가지 일이 일어난다.

① 식별자에 키 → 값으로의 매핑이 정의된다. (Direction["EAST"] = 0)
② 식별자에 값 → 키로의 역방향 매핑이 정의된다. (Direction[Direction["East"] = 0] = "East")
    (문자열 열거형의 경우 역방향 매핑이 존재하지 않는다.)


컴파일된 코드로부터 열거형 멤버에 접근 할 때, 실제로 코드가 실행될 때에도 객체 속성 접근이 발생함을 알 수 있다.

여기서 성능 향상을 위해 const 열거형을 사용할 수 있다.

모든 멤버가 컴파일 시간에 알려진 상수값인 열거형의 경우 const enum 키워드를 이용해 정의할 수 있다.

열거형의 구조는 컴파일 과정에서 사라지고, 멤버의 값은 상수값으로 대체된다.

const enum ConstEnum { 
  A, 
  B = 2, 
  C = B * 2, 
  D = -C, 
} 
console.log(ConstEnum.A); 

위 코드는 아래 자바스크립트 코드로 컴파일된다.

console.log(0 /* A */); 

주석을 제외하고는 열거형의 원래 구조에 대한 어떠한 정보도 남아있지 않고, 상수값으로 대체되어 있다.

 

유니온 열거형

열거형의 모든 멤버가 아래 경우 중 하나에 해당하는 열거형을 유니온 열거형(union enum)이라 부른다.
① 암시적으로 초기화 된 값 (값이 표기되지 않음)
② 문자열 리터럴
③ 숫자 리터럴

예시

enum ShapeKind { 
  Circle, 
  Triangle = 3, 
  Square 
} 

유니온 열거형의 멤버는 값인 동시에 타입이 된다. 따라서 다음과 같은 코드를 작성할 수 있다.

type Circle = { 
  kind: ShapeKind.Circle; 
  radius: number; 
} 
type Triangle = { 
  kind: ShapeKind.Triangle; 
  maxAngle: number; 
} 
type Square = { 
  kind: ShapeKind.Square; 
  maxLength: number; 
} 
type Shape = Circle | Triangle | Square;

유니온 타입을 이용한 열거형 표현
타입스크립트는 숫자, 문자열 그리고 불리언 값을 타입으로 사용하는 리터럴 타입(literal type)을 지원한다. 

리터럴 타입을 이용해 단 하나의 값만을 갖는 타입을 정의할 수 있다.

const answer: 42 = 42; 
const wrongAnswer: 42 = 24; // error TS2322: Type '24' is not assignable to type '42'.

리터럴 타입과 유니온 타입을 조합해 열거형과 유사한 타입을 만들 수 있다.

type Direction = 'EAST' | 'WEST' | 'SOUTH' | 'NORTH'; 
const east: Direction = 'EAST'; 
const center: Direction = 'CENTER'; // error TS2322: Type '"CENTER"' is not assignable to type 'Direction'. 

참고사이트

https://ahnheejong.gitbook.io/ts-for-jsdev

 

'do > typescript' 카테고리의 다른 글

typescript 5  (0) 2019.04.16
typescript 4  (0) 2019.04.14
typescript 2  (0) 2019.04.10
typescript 1  (0) 2019.04.09
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함