TypeScript
DOM 요소의 타입
타입스크립트 자체적으로 DOM API의 타입을 제공한다.
// HTMLElement | null
const link_1 = document.getElementById('myLink');
// Element | null
const link_2 = document.querySelector('#myLink');
// HTMLButtonElement
const btn = document.getElementById('btn') as HTMLButtonElement;
// HTMLParagraphElement
const p = document.createElement('p');
타입 좁히기 Type Narrowing
변수의 가능한 타입을 구체적으로 좁혀나가는 과정을 말한다.
여러 타입의 매개변수에 대해 타입 별로 적절한 처리를 해주기 위해 사용되며,
typeof, instanceof, === 등을 통해 타입의 범위를 좁힐 수 있다.
type Id = string | number;
const id: Id = 1;
function getId(id: Id) {
if (typeof id === 'number') {
return id;
}
return Number(id);
}
type iOS = { iMessage: () => void };
type android = { message: () => void };
function sendMessage(os: iOS | android) {
if ('iMessage' in os) {
os.iMessage();
} else {
os.message();
}
}
class ApiResponse {
data: any;
}
class ErrorResponse {
message: string;
}
const apiResponse = new ApiResponse();
const errorResponse = new ErrorResponse();
function isErrorResponse(
response: ApiResponse | ErrorResponse
): response is ErrorResponse {
return (response as ErrorResponse).message !== undefined;
}
const response = { message: 'error...' };
if (isErrorResponse(response)) {
console.log(response.message);
}
type SuccessResponse {
type:'success',
data: any
}
type ErrorResponse = {
type: 'error',
message: string
}
type ApiResponse = SuccessResponse | ErrorResponse
function handleResponse (response: ApiResponse) {
if(response.type==='success') {
console.log('data:', response.data)
} else{
console.log(response.message)
}
}
고급 타입
교차 타입
여러 타입을 조합하여 사용함으로써, 타입의 재사용성을 높일 수 있다.
type A = { name: string };
type B = { age: number };
type Person = A & B;
const person: Person = {
name: 'John',
age: 33,
};
조건부 타입
type IsNumber<T> = T extends number ? 'Yes' : 'No';
type Result_1 = IsNumber<number>; // 'Yes'
type Result_2 = IsNumber<string>; // 'No'
type JsonOrText<T extends 'json' | 'text'> = T extends 'json' ? object : string;
type JsonResponse = JsonOrText<'json'>; // object
type TextResponse = JsonOrText<'text'>; // string
type MyObject = {
a: number;
b: string;
c: boolean;
};
// MyObject의 key를 literal union 타입으로 추출
type Keys = keyof MyObject; // 'a' | 'b' | 'c'
매핑 타입
type OptionalType<T> = {
[P in keyof T]?: T[P];
};
type ReadonlyType<T> = {
readonly [P in keyof T]: T[P];
};
type UserType = {
id: number;
name: string;
age: number;
email: string;
};
// UserType의 key를 하나씩 돌면서 optional 속성으로 바꾸기
type OptionalUserType = OptionalType<UserType>;
// UserType의 key를 하나씩 돌면서 readonly 속성으로 바꾸기
type ReadonlyUserType = ReadonlyType<UserType>;
유틸리티 타입
| 유틸리티 타입 | 설명 |
|---|---|
Partial<T> |
타입 T의 모든 속성을 optional로 변환 |
Readonly<T> |
타입 T의 모든 속성을 readonly로 변환 |
Pick<T,K> |
타입 T에서 속성 K만 골라 타입 생성 |
Omit<T,K> |
타입 T에서 속성 K를 제외하여 타입 생성 |
Record<K,T> |
K 타입의 key와 T 타입의 값으로 구성된 타입 생성 |
Parameters<T> |
함수 타입 T의 매개변수 타입들을 튜플 타입으로 추출 |
Partial<T>
type User = {
id: number;
name: string;
email: string;
};
type PartialUser = Partial<User>;
const user: PartialUser = {
id: 1,
name: 'Meghan',
};
Readonly<T>
type User = {
id: number;
name: string;
email: string;
};
const user: Readonly<User> = {
id: 1,
name: 'Meghan',
email: 'meghan@email.com',
};
user.id = 10; // error
Pick<T, K>
type User = {
id: number;
name: string;
email: string;
};
type UserWithNameOnly = Pick<User, 'name'>;
const userWithName: UserWithNameOnly = {
name: 'Lee',
};
Omit<T, K>
type User = {
id: number;
name: string;
email: string;
};
type UserWithoutEmail = Omit<User, 'email'>;
type UserWithOnlyEmail = Omit<User, 'id' | 'name'>;
const userWithoutEmail: UserWithoutEmail = {
id: 2,
name: 'Meghan',
};
const userWithOnlyEmail: UserWithOnlyEmail = {
email: 'meghan@email.com',
};
Record<K, T>
type Country = 'South Korea' | 'United States' | 'Canada';
type Capital = string;
type CountryCapitals = Record<Country, Capital>;
const capitals: CountryCapitals = {
'South Korea': 'Seoul',
'United States': 'Washington D.C.',
'Canada': 'Ottawa',
};
type CountryInfo = {
capital: string;
population: number;
continent: string
}
type CountryInfoMap = Record<Country, CountryInfo>
cons countryInfo: CountryInfoMap = {
'South Korea': {
capital: 'Seoul',
population: 51_000_000,
continent: 'Asia'
},
'United States': {
capital: 'Washington D.C.',
population: 331_000_000,
continent: 'North America'
},
'Canada': {
capital: 'Ottawa',
population: 83_000_000,
continent: 'North America'
},
}
Parameters<T>
type User = (id: number, name: string) => void;
type Params = Parameters<User>; // [id: name, name: string]
function saveUser(...params: Params) {
const [id, name] = params;
}
saveUser(1, 'Meghan');
상수 단언
const someObject = {} as const
배열 또는 객체를 리터럴 타입이자 변경 불가능한 상태로 만듦으로써,
컴파일러의 정확한 타입 추론을 돕고, 코드 범위 내에서 불변성을 유지하도록 돕는다.
const book = {
title: 'book title',
author: 'book author',
} as const;
// book.title = "book title changed";
// error: Cannot assign to 'title' because it is a read-only property.
const numbers = [1, 2, 3, 4, 5] as const;
// numbers.push(6);
// error: Property 'push' does not exist on type 'readonly [1, 2, 3, 4, 5]'
const statusCodeMap = {
101: 'ordered',
102: 'pending',
103: 'completed',
} as const;
type statusCodeKeys = keyof typeof statusCodeMap; // 101 \ 102 | 103
function handleStatus(statusCode: statusCodeKeys) {
const message = statusCodeMap[statusCode]; // 'ordered' | 'pending' | 'completed'
}'Notes > TypeScript' 카테고리의 다른 글
| TypeScript Chapter. 5 (1) | 2024.12.09 |
|---|---|
| TypeScript Chapter. 3 (0) | 2024.12.07 |
| TypeScript Chapter. 2 (1) | 2024.12.07 |
| TypeScript Chapter. 1 (1) | 2024.12.05 |