리터럴 타입
var 또는 let 으로 변수를 선언할 경우 이 변수의 값이 변경될 가능성이 있음을 컴파일러에게 알린다. 반면, const 로 변수를 선언하게 되면 TypeScript 에게 이 객체는 절대 변경되지 않음을 알린다. 그렇기 때문에 const 로 선언된 변수는 number, string 과 같은 기본 타입이 아닌 변수 값 자체가 타입이 되는데, 이것을 리터럴 타입이라고 부른다. 각 리터럴 타입은 number, string 같은 더 큰 타입에 포함된다.
const name = 'codeit'; // 'codeit' 이라는 리터럴 타입
const rank = 1; // 1 이라는 리터럴 타입
타입 별칭
타입 별칭은 복잡한 타입에 이름을 붙여 재사용하고 싶을 때 사용한다. 타입 별칭은 type 뒤에 별칭을 쓰고 = 연산자 뒤에 타입을 정의하는 방식으로 사용할 수 있다. 별칭은 다른 변수와 차별화를 위해 관습적으로 대문자로 시작한다.
type Point = [number, number];
type SearchQuery = string | string[];
type Result = SuccessResult | FailedResult;
type Coupon =
| PromotionCoupon
| EmployeeCoupon
| WelcomCoupon
| RewardCoupon
;
Union
A 이거나 B 인 경우를 타입으로 만들고 싶을 때 사용한다. 아래의 코드에서 함수의 매개변수 product 는 ClothingProduct 또는 ShoeProduct 둘 중 하나의 타입이면 된다.
function func(product: ClothingProduct | ShoeProduct) {
// ...
}
그럼 ClothingProduct 또는 ShoeProduct 두 타입 중 하나에만 있는 프로퍼티에 대한 내용은 어떻게 작성해야 할까?
if 문에 in 키워드를 사용해서 해당 프로퍼티가 있는지 검사하면 된다. 이런 식으로 타입의 범위를 좁히는 것을 Type Narrowing 이라고 한다.
interface A {
a: string;
}
interface B {
b: number;
}
function printAUnionB(arg: A | B) {
// 여기서는 타입 A | B
if ('a' in arg) {
// 여기 안에서는 타입 A
console.log(arg.a);
}
if ('b' in arg) {
// 여기 안에서는 타입 B
console.log(arg.b); // VS Code에서 arg에 마우스를 호버해 보세요.
}
}
Intersection
A 와 B 의 성질을 모두 갖는 타입을 만들고 싶을 때 사용한다.
interface Entity {
id: string;
createdAt: Date;
updatedAt: Date;
}
type Product = Entity & {
name: string;
price: number;
membersOnly?: boolean;
}
하지만, 보통 이럴 때는 interface 와 상속을 사용하는 것을 권장한다.
interface Entity {
id: string;
createdAt: Date;
updatedAt: Date;
}
interface Product extends Entity {
name: string;
price: number;
membersOnly?: boolean;
}
※ Union 과 Intersection
- A | B -> A 타입이거나 B 타입
- A & B -> A 타입이랑 B 타입을 합친 것
근데 헷갈리는 것이 있다. 수학에서 배웠던 집합을 떠올려보면 Union(합집합), Intersection(교집합)과 같은 용어를 떠올려보면 아래와 같은 그림이 떠오른다. 아래의 그림을 생각하면 Union 은 두 타입을 합치고 Intersection 은 두 타입의 공통된 부분만 가져야 할 것 같다.

Structural Subtyping
타입스크립트에서 타입은 Structural Subtyping 이라는 규칙을 따른다. 쉽게 말해 구조가 같으면 같은 타입이라고 판단하는 것이다.
타입 A 는 a 라는 프로퍼티를 가지고 있고 변수 x, z, w 에 담겨있는 있는 각 객체에는 a 라는 프로퍼티가 존재한다. 그래서 타입 A 의 a 프로퍼티를 출력하는 printA 함수에 x, z, w 변수를 넣고 실행해도 올바른 타입이지만, a 프로퍼티가 없는 변수 y 에 담긴 객체로 실행하면 타입에러가 발생한다.
이처럼 객체에 a 라는 프로퍼티가 있기 때문에 타입 A 라고 판단하는 것을 Structural Subtyping, Structural Type System 이라고 한다. (쉽게 말해 같은 것이 있으면 같은 타입으로 판단한다는 것)
interface A {
a: string;
}
interface B {
b: number;
}
function printA(arg: A) {
console.log(arg.a);
}
const x = { a: 'codeit' };
const y = { b: 42 };
const z = { a: 'codeit', b: 42 };
const w = { a: 'codeit', b: 42, c: true };
printA(x);
printA(y); // 잘못된 타입
printA(z);
printA(w);
- Union 타입

- Intersection 타입

keyof 연산자
객체 타입에서 프로퍼티 이름들을 모아서 Union 한 개의 Union 타입으로 만들고 싶을 때 사용한다.
interface Product {
id: string;
name: string;
price: number;
membersOnly?: boolean;
}
type ProductProperty = keyof Product; // 'id' | 'name' | 'price' | 'membersOnly';
typeof 연산자
자바스크립트 코드에서 사용하면 결괏값이 문자열이지만, 타입스크립트 코드에서 쓸 때는 결과 값은 타입스크립트의 타입이다.
// js 코드
const product: Product = {
id: 'c001',
name: '코드잇 블랙 후드 집업',
price: 129000,
salePrice: 98000,
membersOnly: true,
};
console.log(typeof product); // 문자열 'object'
// ts 코드
const product: Product = {
id: 'c001',
name: '코드잇 블랙 후드 집업',
price: 129000,
salePrice: 98000,
membersOnly: true,
};
const product2: typeof product = { // 타입스크립트의 Product 타입 -> 특정 객체 타입으로 사용할 수 있다
id: 'g001',
name: '코드잇 텀블러',
price: 25000,
salePrice: 19000,
membersOnly: false,
};
'웹 > TypeScript' 카테고리의 다른 글
[TypeScript] 타입스크립트 공부하기-1 (3) | 2024.11.12 |
---|---|
[TypeScript/타입스크립트] 기본 문법 정리 -1 (1) | 2024.06.14 |