유니온(Union)타입
- 유니온 타입은 하나의 프로퍼티에 다양한 변수가 올 수 있는 타입을 말합니다.
let args: number | string;
let arg: 'a' | 'b' | 'c';
keyof 키워드
- keyof 키워드는 타입 값에 존재하는 모든 프로퍼티의 키값을 union 형태로 리턴 받습니다.
interface Todo {
id: number;
text: string;
due: Date;
}
type TodoKeys = keyof Todo;
never 타입
- never는 에러가 발생했을 때 프로세스를 중단시키지 않고 무시하는 타입입니다.
- any를 제외한 다른 모든 타입의 원시 타입으로 사용 가능합니다.
- 타입이기는 하지만 실제 never 타입으로 변수를 선언할 수 없고 주로 함수의 리턴 타입으로 에러가 발생할 경우 에러를 무시하고 계속 진행시키는 역할을 합니다.
- never 타입은 절대로 발생하지 않는 값의 타입을 나타냅니다. 예를 들어, never는 함수 표현식의 리턴 타입이거나, 항상 예외를 던지는 화살표 함수 표현식이거나, 리턴하지 않는 표현식입니다. 변수는 결코 true가 될 수 없는 어떤 타입의 가드에 의해 좁혀 질 때 타입 never를 획득합니다.
- never 타입은 모든 타입의 서브 타입이며, 모든 타입에 assign 가능합니다. 하지만 어떤 타입도 never (never 자체 제외)의 하위 타입이 아니고 assign 할 수 없습니다. 어떤 타입도 ‘never’에 assign되지 않습니다.
function error(message: string): never {
throw new Error(message);
}
function fail() {
return error('Something failed');
}
function infiniteLoop(): never {
while (true) {}
}
Partial
- 모든 속성이 선택 사항으로 설정된 유형을 구성합니다.
- 이 유틸리티는 주어진 유형의 모든 하위 집합을 나타내는 유형을 반환합니다.
- 타입 T의 모든 프로퍼티를 Optional 형태로 바꾸어줍니다.
- Partial은 타입은 원시 타입에 해당하는 프토 퍼티 값을 할당할 수도 안 할 수도 있지만 원시 타입에 존재하지 않는 값은 할당할 수 없습니다.
type Partial<T> = { [P in keyof T]?: T[P] };
interface User {
name: string;
age: number;
}
let user1: User = { name: 'harry', age: 23 };
let user2: User = { age: 23 };
let user2: Partial<User> = { age: 23 };
interface Todo {
title: string;
description: string;
}
function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
return { ...todo, ...fieldsToUpdate };
}
const todo1 = {
title: 'organize desk',
description: 'clear clutter',
};
const todo2 = updateTodo(todo1, {
description: 'throw out trash',
});
Required
- 모든 속성이 필수로 설정된 유형으로 구성합니다.
- 모든 Optional 타입들을 언랩핑합니다.
- 마이너스 연산자는 옵셔널을 제거해주는 연산자입니다.
- partials에서 물음표 연산자만 사용한 것처럼 플러스 연산자를 생략할 수 있습니다.
type Required<T> = {
[P in keyof T]-?: T[P];
};
type MutableRequired<T> = { -readonly [P in keyof T]-?: T[P] };
type ReadonlyPartial<T> = { +readonly [P in keyof T]+?: T[P] };
interface Props {
a?: number;
b?: string;
}
const obj: Props = { a: 5 };
const obj2: Required<Props> = { a: 5 };
Readonly
- 읽기만 가능한 프로퍼티를 선언할 때 사용된다.
- 생성 된 유형의 속성을 재 할당 할 수 없습니다.
- 모든 프로퍼티를 값을 참조만 할 수 있도록 바꿉니다.
- Partial과 비슷하지만 옵셔널(=?)이 아닌 readonly 키워드를 사용합니다.
type Readonly<T> = { readonly [P in keyof T]: T[P] };
interface Card {
name: string;
price: number;
}
type readOnlyCard = Readonly<Card>;
let readonlyUser: readOnlyCard = { name: "Sonata", price: 10000 };
readonlyUser.price = 3;
interface Todo {
title: string;
}
const todo: Readonly<Todo> = {
title: 'Delete inactive users',
};
todo.title = 'Hello';
Record<K,T>
- K타입을 Key값 타입으로, T타입을 밸류 값 타입으로 갖는 타입을 리턴합니다.
- 타입 K와 T를 받아 타입 K를 프로퍼티 키값으로 하는 타입을 만들 수 있습니다. 주로 K에 유니온 문자열 값을 주어 map 형식의 타입을 만들 수 있고 여러 값들을 원하는 키값에 따라 분류할 때 유용합니다.
type Record<K extends keyof any, T> = {
[P in K]: T;
};
export interface Car {
name: string;
price: number;
}
const productList: Record<'SONATA' | 'AVANTE', Car> = {
SONATA: { name: 'SONATA', price: 10000 },
AVANTE: { name: 'SONATA', price: 10000 },
};
const nextProductList: Record<string, Car> = {
SONATA: { name: 'SONATA', price: 10000 },
AVANTE1: { name: 'SONATA', price: 10000 },
AVANTE2: { name: 'SONATA', price: 10000 },
AVANTE3: { name: 'SONATA', price: 10000 },
};
type memo = { content: string; date: string };
const FRIENDS_LIST = ['harry', 'jason', 'dukkey'] as const;
type FriendTypeArray = typeof FRIENDS_LIST[number];
type friendType = Record<FriendTypeArray, memo>;
Pick<T,K>
- T 타입으로부터 K 프로퍼티만 추출합니다.
- 특성 세트를 선택하여 유형을 구성합니다.
- 키값 T에 속하는 유니온 타입 K를 받아(= K extends keyof T) 매칭 되는 프로퍼티만 리턴합니다.( = [P in K: T [P])
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = Pick<Todo, 'title' | 'completed'>;
const todo: TodoPreview = {
title: 'Clean room',
completed: false,
};
## Exclude<T,U>
- T 타입들중 U타입들과 겹치는 타입을 제외합니다.
- 타입 T가 타입 U를 상속하거나 동일 타입이라면 무시(never)하고 아닐 경우 타입 값을 리턴합니다. 타입 T 또는 타입 U가 유니온 타입으로 온다면 각각의 교집합이 무시(never)됩니다.
type Exclude<T, U> = T extends U ? never : T;
type T0 = Exclude<'a' | 'b' | 'c', 'a'>;
type T1 = Exclude<'a' | 'b' | 'c', 'a' | 'b'>;
type T2 = Exclude<string | number | (() => void), Function>;
- T타입에서 U타입과 겹치는 타입만을 가져옵니다.
- Exclude와 거의 비슷하지만 T와 never의 위치만 다르기 때문에 교집합을 리턴합니다.
type Extract<T, U> = T extends U ? T : never;
type T0 = Extract<'a' | 'b' | 'c', 'a' | 'f'>;
type T1 = Extract<string | number | (() => void), Function>;
Omit<T,K>
- 특정 인터페이스에서 원하지 않는 속성을 제외하는 타입 입니다.
- Pick과는 정반대로 T타입으로부터 K프토퍼티를 제거합니다.
- Pick과 Exclude를 한 곳에 넣어놓고 보면 다소 가독성이 떨어져 이해하기 난감할 수 있는데 아래 코드를 보시면 조금 더 쉽게 이해할 수 있습니다.
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
type Car = {
name: string;
price: number;
brand: string;
};
type RemainingKeys = Exclude<keyof Car, 'brand'>;
type NoBrandCard = Pick<Car, RemainingKeys>;
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
interface Test {
a: string;
b: number;
c: boolean;
}
type OmitA = Omit<Test, 'a'>;
type OmitAB = Omit<Test, 'a' | 'b'>;
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = Omit<Todo, 'description'>;
const todo: TodoPreview = {
title: 'Clean room',
completed: false,
};
NonNullable
- T타입에서 null or undefinded을 제외하고 리턴합니다.
- null 혹은 undefined 타입이거나 상속한다면 무시(never) 아니라면 타입을 리턴합니다.
type NonNullable<T> = T extends null | undefined ? never : T;
type T0 = NonNullable<string | number | undefined>;
type T1 = NonNullable<string[] | null | undefined>;
Parameters
- 함수의 파라미터를 타입으로 리턴합니다.
- T는 (…args: any) => any로 선언되어있습니다. 모든 파라미터를 인자로 받고 결괏값으로 모든 값을 리턴하기 때문에 사실상 모든 함수를 상속합니다.
- infer 키워드는 타입 스크립트가 엔진이 런타임 상황에서 타입을 추론할 수 있도록 하고 그 값을 P에 할당해줍니다. 파라미터 타입을 infer P로 할당하고 함수의 형태가 참이라면 파라미터를 아니라면 무시(never)합니다.
- any와 never 모두 함수를 대신하여 파라미터 타입으로 사용할 수 있기 때문에 에러가 발생하지 않습니다.
type Parameters<T extends (...args: any) => any> = T extends (
...args: infer P
) => any
? P
: never;
declare function f1(arg: { a: number; b: string }): void;
type T0 = Parameters<() => string>;
type T1 = Parameters<(s: string) => void>;
type T2 = Parameters<<T>(arg: T) => T>;
type T4 = Parameters<typeof f1>;
type T5 = Parameters<any>;
type T6 = Parameters<never>;
type T7 = Parameters<string>;
type T8 = Parameters<Function>;
ConstructorParameters
- 생성자를 갖는 함수 타입의 생성자 파라미터를 리턴합니다. 함수가 아니라면 never를 리턴합니다.
- 위의 parameters와 비슷하지만 new키워드를 추가하여 생성자 파라미터로 한정하였습니다.
type ConstructorParameters<T extends new (...args: any) => any> =
T extends new (...args: infer P) => any ? P : never;
class Person {
private _firstname: string;
private _lastname: string;
constructor(firstname: string, lastname: string) {
this._firstname = firstname;
this._lastname = lastname;
}
}
type constructuinArgsType = ConstructorParameters<typeof Person>;
let personConstructionArgs: constructuinArgsType = ['first', 'last'];
ReturnType
- 함수의 리턴타입을 가져옵니다.
- parameter와 비슷하지만 타입 추론(infer)을 함수의 결괏값에 할당한 후 리턴합니다.
type ReturnType<T extends (...args: any) => any> = T extends (
...args: any
) => infer R
? R
: any;
let f1 = () => ({ a: 23, b: 33 });
type T0 = ReturnType<() => string>;
type T1 = ReturnType<(s: string) => void>;
type T2 = ReturnType<<T>() => T>;
type T3 = ReturnType<<T extends U, U extends number[]>() => T>;
type T4 = ReturnType<typeof f1>;
InstanceType
- 생성자로 초기화된 인스턴스 타입을 리턴합니다.
- 타입 추론(infer)을 인스턴스 값에 할당한 후 리턴하였습니다.
type InstanceType<T extends new (...args: any) => any> = T extends new (
...args: any
) => infer R
? R
: any;
let funTest = () => ({ a: 23, b: 33 });
type T0 = ReturnType<() => string>;
type T1 = ReturnType<(s: string) => void>;
type T2 = ReturnType<<T>() => T>;
type T3 = ReturnType<<T extends U, U extends number[]>() => T>;
type T4 = ReturnType<typeof funTest>;
type T5 = ReturnType<any>;
type T6 = ReturnType<never>;