유틸리티 타입

2022. 12. 27. 19:33프로그래밍/TypeScript

Utility Types

타입스크립트에서 제공하는 여러가지 전역 유틸리티 타입

 

참고

Utility Types

 

Documentation - Utility Types

Types which are globally included in TypeScript

www.typescriptlang.org


Partial

TYPE의 모든 속성을 선택적(?)으로 변경한 새로운 타입 반환
Partial<TYPE>
interface IUser {
  name: string,
  age: number
}

const userA: IUser = { // Error. age 속성 필요
  name: 'A'
};

const userB: Partial<IUser> = {
  name: 'B'
};

// Partial<IUser> 과 같음
interface INewType {
  name?: string,
  age?: number
}

 

Required

TYPE의 모든 속성을 필수로 변경한 새로운 타입 반환
Required<TYPE>
interface IUser {
  name?: string,
  age?: number
}

const userA: IUser = {
  name: 'A'
};

const userB: Required<IUser> = { // Error. age 속성 필요
  name: 'B'
};

// Required<IUser> 와 같음
interface IUser {
  name: string,
  age: number
}

 

Readonly

TYPE의 모든 속성을 읽기 전용으로 변경한 새로운 타입 반환
Readonly<TYPE>
interface IUser {
  name: string,
  age: number
}

const userA: IUser = {
  name: 'A',
  age: 12
}
userA.name = 'AA';

const userB: Readonly<IUser> = {
  name: 'B',
  age: 13
}
userB.name = 'BB'; // Error. name 은 읽기 전용이므로 할당 불가능

// Readonly<IUser> 와 같음
interface INewType {
  readonly name: string,
  readonly age: number
}

 

Record

KEY를 속성으로, TYPE을 그 속성값의 타입으로 지정하는 새로운 타입 반환
Record<KEY, TYPE>
type TName = 'neo' | 'lewis';

const developers: Record<TName, number> = {
  neo: 12,
  lewis: 13
};

// Record<TName, number> 와 같음
interface INewType {
  neo: number,
  lewis: number
}

 

Pick

TYPE에서 KEY로 속성을 선택한 새로운 타입 반환
TYPE속성을 가지는 인터페이스/객체 타입이어야 함
Pick<TYPE, KEY>
interface IUser {
  name: string,
  age: number,
  email: string,
  isValid: boolean
}
type TKey = 'name' | 'email'

const user: Pick<IUser, TKey> = {
  name: 'Neo',
  email: 'thesecon@gmail.com',
  age: 22 // Error. age 속성 할당 불가
}

// Pick<IUser, TKey> 와 같음
interface INewType {
  name: string,
  email: string
}

 

Omit

TYPE에서 KEY로 속성을 생략하고 나머지를 선택한 새로운 타입 반환
TYPE속성을 가지는 인터페이스/객체 타입이어야 함
Pick과 반대
Omit<TYPE, KEY>
interface IUser {
  name: string,
  age: number,
  email: string,
  isValid: boolean
}
type TKey = 'name' | 'email';

const user: Omit<IUser, TKey> = {
  age: 22,
  isValid: true,
  name: 'Neo' // Error. age, isValid 속성 할당 불가능
}

// Omit<IUser, TKey> 과 같음
interface INewType {
  // name: string, 생략
  age: number,
  // email: string, 생략
  isValid: boolean
}

 

Exclude

유니언 TYPE1에서 유니언 TYPE2를 제외한 새로운 타입 반환
Exclude<TYPE1, TYPE2>
type T = string | number;

const a: Exclude<T, number> = 'Only string';
const b: Exclude<T, number> = 1234; // Error. string 타입만 할당 가능
const c: T = 'String';
const d: T = 1234;

 

Extract

유니언 TYPE1에서 유니언 TYPE2를 추출한 새로운 타입 반환
Extract<TYPE1, TYPE2>
type T = string | number;
type U = number | boolean;

const a: Extract<T, U> = 123;
const b: Extract<T, U> = 'Only number' // Error. number	타입만 할당 가능

 

NonNullable

유니언 TYPE에서 null, undefined를 제외한 새로운 타입 반환
NonNullable<TYPE>
type T = string | number | undefined;

const a: T = undefined;
const b: NonNullable<T> = null; // Error. string, number 타입만 할당 가능

 

Parameters

함수 TYPE의 매개변수 타입을 새로운 튜플 타입으로 반환
Parameters<TYPE>
function fn(a: string | number, b: boolean) {
  return `[${a}, ${b}]`; // [string | number, boolean]
}

const a: Parameters<typeof fn> = ['Hello', 123]; // Error. [string | number, boolean] 타입만 가능

// Parameters<typeof fn> 와 같음
[string | number, boolean]

 

ConstructorParameters

클래스 TYPE의 매개변수 타입을 새로운 튜플 타입으로 반환
ConstructorParameters<TYPE>
class User {
  constructor (public name: string, private age: number) {} // [string, number]
}
const neo = new User('Neo', 12);

const a: ConstructorParameters<typeof User> = ['Neo', 12];

// Error. [string, number] 타입만 할당 가능
const b: ConstructorParameters<typeof User> = ['Lewis']; 

// ConstructorParameters<typeof User> 와 같음
[string, number]

 

ReturnType

함수 TYPE의 반환 타입을 새로운 타입으로 반환
ReturnType<TYPE>
function fn(str: string) {
  return str; // string
}

const a: ReturnType<typeof fn> = 'Only string';
const b: ReturnType<typeof fn> = 1234; // Error. string 타입만 할당 가능

 

InstanceType

클래스 TYPE의 인스턴스 타입 반환
InstanceType<TYPE>
class User {
  constructor(public name: string) {}
}

// User 클래스의 인스턴스 === new User('Neo')
const neo: InstanceType<typeof User> = new User('Neo');

 

ThisParameterType

함수 TYPE의 명시적 this 매개변수 타입을 새로운 타입으로 반환
함수 TYPE에 명시적 this 매개변수가 없을 경우 Unknown 반환
ThisParameterType<TYPE>
function toHex(this: Number) {
  return this.toString(16); // this: Number
}

function numberToString(n: ThisParameterType<typeof toHex>) { // n: Number
  // toHex 함수의 this에 n을 바인딩하고 호출함
  // toHex에 다른 타입의 this가 바인딩 되는 것을 방지함
  return toHex.apply(n); 
}

 

OmitThisParameter

함수 TYPE의 명시적 this 매개변수를 제거한 새로운 타입 반환
OmitThisParameter<TYPE>
function getAge(this: typeof cat) {
  return this.age;
}

// 기존 데이터
const cat = {
  age: 12 // Number;
}
getAge.call(cat); // 12

// 새로운 데이터
const dog = {
  age: '13'; // String
}
 // Error. age 속성은 number 타입이어야 함
getAge.call(dog);
// getAge 함수의 명시적 this를 제거함 (number타입)
// this.age 에는 어떤 값도 들어갈 수 있음
const getAgeForDog: OmitThisParameter<typeof getAge> = getAge;

// this는 string 타입이 될 수 있음
getAgeForDog.call(dog); // '13'

 

ThisType

TYPE의 this 컨텍스트를 명시하고 별도의 타입을 반환하지 않음
ThisType<TYPE>
interface IUser {
  name: string,
  getName: () => string
}

function makeNeo(methods: ThisType<IUser>) {
  // ThisType은 타입을 반환하지 않으므로 타입 단언을 해주어야 함
  return { name: 'Neo', ...methods } as IUser;
}

// this.name 을 사용함
// 명시적으로 this를 설정해 주어야 함
// makeNeo 함수의 파라미터 타입을 ThisType<IUser>로 설정
const neo = makeNeo({
  getName() {
    return this.name;
  }
});

neo.getName(); // Neo