Enum
- 중괄호 안에서 각 항목을 쉼표로 구분해서 적어주면 됨
- 기본값은 0부터 시작하는 정수임
enum Size {
S,
M,
L,
XL,
}
console.log(Size.S);
console.log(Size.M);
console.log(Size.L);
- 숫자 0은 실수하기 쉽기 때문에 Enum을 사용할 땐 되도록이면 값을 정해놓고 쓰는 게 좋음
enum Size {
S = 'S',
M = 'M',
L = 'L',
XL = 'XL',
}
Interface
- interface를 사용하는 방법은 interface를 쓴 다음, 객체 타입처럼 만들면 됨
interface Product {
id: string;
name: string;
price: number;
membersOnly?: boolean;
}
- Interface를 상속하고 싶으면 Interface 이름 뒤에 extends를 적은 다음 부모 Interface 이름을 적어주면 됨
interface ClothingProduct extends Product {
sizes: Size[];
}
const product1: ClothingProduct = {
id: 'c001',
name: '코드잇 블랙 후드 집업',
price: 129000,
membersOnly: true,
sizes: [Size.M, Size.L],
};
const product2: Product = {
id: 'd001',
name: '코드잇 텀블러',
price: 25000,
};
그 밖의 타입들
리터럴 타입
- 특정한 숫자나 문자열 같이 변수의 값을 타입으로 하는 타입
- 문자열 리터럴 타입은 문자열 타입에 포함되고 숫자 리터럴 타입은 숫자형 타입에 포함됨
const name = 'codeit';
const rank = 1;
타입 별칭:
- 타입도 변수처럼 이름을 붙여줄 수 있는데 이를 타입 별칭이라 함
- 복잡한 타입에 이름을 붙이고 재사용하고 싶을 때 사용
- 모든 타입에 사용할 수 있음
type Cart = string[];
type CartResultCallback = (result: boolean) => void;
type Prodect = {
id: string;
name: string;
}
interface Prodect = {
id = string;
name: string;
}
type Point = [number, number];
type SearchQuery = string | string[];
type Result = SuccessResult | FailedResult;
type Coupon =
| PromotionCoupon
| EmployeeCoupon
| WelcomCoupon
| RewardCoupon
;
Union 타입
- A이거나 또는 B인 경우를 타입으로 만들고 싶을 때
ClothingProduct | ShoeProduct
- 타입으로 연산도 가능함
- if문을 활용하면 유니언 타입에서 특정 타입만 처리하도록 할 수 있음
enum ClothingSize {
S = 'S',
M = 'M',
L = 'L',
XL = 'XL',
}
interface Product {
id: string;
name: string;
price: number;
membersOnly?: boolean;
}
interface ClothingProduct extends Product {
sizes: ClothingSize[];
color: string;
}
interface ShoeProduct extends Product {
sizes: number[];
handmade: boolean;
}
function printSizes(product: ClothingProduct | ShoeProduct) {
const availableSizes = product.sizes.join(', ');
console.log(`구매 가능한 사이즈는 다음과 같습니다: ${availableSizes}`);
if ('color' in product) {
console.log(`색상: ${product.color}`);
}
}
if ('handmade' in product) {
console.log(
product.handmade
? '이 상품은 장인이 직접 만듭니다.'
: '이 상품은 공장에서 만들어졌습니다.'
);
}
}
const product1: ClothingProduct = {
id: 'c001',
name: '코드잇 블랙 후드 집업',
price: 129000,
membersOnly: true,
sizes: [ClothingSize.M, ClothingSize.L],
color: 'black',
};
const product2: ShoeProduct = {
id: 's001',
name: '코드잇 스니커즈',
price: 69000,
membersOnly: false,
sizes: [220, 230, 240, 260, 280],
handmade: false,
};
printSizes(product1);
printSizes(product2);
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;
}
keyof 연산자
- 객체 타입에서 프로퍼티 이름들을 모아서 Union한 타입으로 만들고 싶을 때 사용
interface Product {
id: string;
name: string;
price: number;
membersOnly?: boolean;
}
type ProductProperty = keyof Product;
typeof 연산자
- 자바스크립트 코드에서 사용하면 결괏값이 문자열이지만, 타입스크립트 코드에서 쓸 때는 결과 값은 타입스크립트의 타입임
const product: Product = {
id: 'c001',
name: '코드잇 블랙 후드 집업',
price: 129000,
salePrice: 98000,
membersOnly: true,
};
console.log(typeof product);
const product2: typeof product = {
id: 'g001',
name: '코드잇 텀블러',
price: 25000,
salePrice: 19000,
membersOnly: false,
};
타입 별칭은 언제 쓰면 좋을까?
- 타입 별칭은 타입에 '이름'을 정하는 문법임
- 복잡한 타입을 만들고, 그 타입을 여러 곳에서 활용할 때 사용하면 됨
제네릭
<>
안에 임의의 타입을 정의해 놓고 그때 그때 다른 타입을 넣어서 쓸 수 있도록 하는 문법
- 보통 알파벳 T, U, V로 나타내며 Type parameter를 나타냄
const shoeSizes: number[] = [230, 250, 280];
shoeSizes.map((num) => {
});
const clothingSizes: string[] = ['M', 'L', 'XL'];
clothingSizes.map((names) => {
});
function printArray<T>(items: T[]) {
for (const item of items) {
console.log(item);
}
}
printArray(shoeSizes);
printArray(clothingSizes);
알아두면 유용한 제네릭 타입들
JavaScript 기능들
querySelector()
함수
- 기본적으로 어떤 DOM 노드가 리턴될지 모르기 때문에
HTMLElement
라는 일반적인 타입으로 정의됨
- 타입을 확신할 수 있는 경우에는 아래 코드처럼 직접 제네릭 타입을 정의해 주면 됨
const elem = document.querySelector<HTMLInputElement>('input.username');
Map
- 키와 밸류를 갖는 자료구조로 타입 파라미터로 키와 밸류의 타입을 정의하고 사용할 수 있음
const productMap = new Map<string, Product>();
productMap.set(product1.id, product1);
productMap.set(product2.id, product2);
Set
- 배열과 비슷하지만 중복된 요소를 추가할 수 없는, 수학에서 집합에 해당하는 자료구조임
- 타입 파라미터로 요소의 타입을 정의하고 사용할 수 있음
const productSet = new Set<Product>();
productSet.add(product1);
productSet.add(product2);
유용한 타입들
키와 밸류 정하기: Record
- 객체에 키와 밸류 타입을 정해놓고 싶을 때 사용함
Map
과 비슷하지만 차이점은 순수한 객체에 타입만 추가한다는 점
const productMap: Record<string, Product> = {}
productMap['c001'] = product1;
productMap['c002'] = product2;
객체 프로퍼티 고르기: Pick
interface Product {
id: string;
name: string;
price: number;
membersOnly?: boolean;
}
type ProductInfo = Pick<Product, 'name' | 'price'>;
- Pick으로 만든 타입은 아래와 같으며
name
프로퍼티와 price
프로퍼티만 골라서 타입을 만듦
type ProductInfo = {
name: string;
price: number;
}
객체의 프로퍼티 생략하기: Omit
interface Product {
id: string;
name: string;
price: number;
membersOnly?: boolean;
}
type ProductInfo = Omit<Product, 'id' | 'membersOnly'>;
- Omit으로 만든 타입은 아래와 같으며 id와 membersOnly를 제외하고 타입을 만듦
type ProductInfo = {
name: string;
price: number;
}
Union 제거하기: Exclude
- Employee Coupon에 해당하는 것만 제거를 하고 싶을 때 Exclude를 사용할 수 있음
type Coupon =
| PromotionCoupon
| EmployeeCoupon
| WelcomCoupon
| RewardCoupon
;
type InternalCoupon = EmployeeCoupon;
type PublicCoupon = Exclude<Coupon, InternalCoupon>;
함수 파라미터 타입 가져오기: Parameters
- 함수 파라미터들의 타입을 함수의 타입을 통해 정의할 수 있음
- 만약 함수의 타입이 아니라, 선언된 함수라면 typeof 연산자로 함수의 타입으로 만들어서 사용하면 됨
function addToCart(id: string, quantity: number = 1): boolean {
return true;
}
type AddToCartParameters = Parameters<typeof addToCart>;
함수 리턴 타입 가져오기: ReturnType
- Parameters와 마찬가지로 함수의 리턴 타입을 가져옴
function addToCart(id: string, quantity: number = 1): boolean {
return true;
}
type AddToCartResult = ReturnType<typeof addToCart>;