능히 해낼 수 있다

230822 TypeScript: 유틸리티 타입 본문

개발🌐/TypeScript

230822 TypeScript: 유틸리티 타입

roni_eo 2023. 8. 22. 15:10
반응형

✍️✍️✍️ 위 글은 작성자의 지식습득에 따라 추후 퇴고 될 수 있음을 알려드립니다(피드백 환영).


타입스크립트는 유틸리티 타입(utility type)이라는 특별한 타입을 제공하여 타입 정의를 간소화하고 재사용성을 높여주는 기능을 제공한다. 이러한 유틸리티 타입들은 이미 정의된 기존 타입을 변환하거나 결합하여 새로운 타입을 생성하는 데 사용되며, 유틸리티 타입을 사용하면 타입 코드를 더 간결하게 작성하고 중복을 줄이며 유지보수성을 향상시킬 수 있다.

1. keyof

keyof는 TypeScript에서 사용되는 유틸리티 타입 중 하나로 객체 타입의 모든 키를 유니언 타입으로 추출할 수 있다. 주로 제네릭 타입 및 인덱스 시그니처와 함께 사용되어 타입 안전성을 확보하고 동적으로 속성 이름에 액세스할 때 유용하다.

type Person = {
  name: string;
  age: number;
  address: string;
};

//Person 객체 타입의 키를 추출하기위해 keyof를 사용하여 PersonKey 타입을 정의
type PersonKey = keyof Person; // "name" | "age" | "address" 이것과 똑같음
//  PersonKey는 "name", "age", "address"와 같은 문자열 리터럴 유니온 타입이됨

keyof를 사용하면 객체의 속성 이름을 문자열 리터럴로 사용할 수 있으므로, 다음과 같이 동적으로 속성에 접근할 때 유용하다

//getProperty 함수: 객체와 키를 입력으로 받아 해당 키에 대한 값을 반환
// key의 타입이 keyof T와 호환되도록 하여 타입 안전성을 확보
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const person: Person = {
  name: "Mimi",
  age: 28,
  address: "123 Main St",
};

const name: string = getProperty(person, "name"); // OK
const age: number = getProperty(person, "age"); // OK
const invalidKey: boolean = getProperty(person, "invalidKey"); // 에러: 유효하지 않은 키 사용

2. Partial <T>

Partial 유틸리티 타입은  프로퍼티를 옵션으로 바꿔주기 때문에 일부만 사용이 가능하다. 그말은 제네릭 타입 T의 모든 속성을 선택적으로 만들어 객체를 부분적으로 업데이트하고자 할 때 유용하다.

type Person = {
  name: string;
  age: number;
};

const partialPerson: Partial<Person> = { name: "Mimi" }; // age 속성은 선택적으로 변경 가능

3. Required<T>

Required 유틸리티 타입은 Partial과 달리 제네릭 타입 T의 모든 속성을 필수로 만든다.

type PartialPerson = Partial<Person>;
type RequiredPerson = Required<PartialPerson>; // name과 age 모두 필수 속성

4. Readonly<T>

Readonly 유틸리티 타입은 제네릭 타입 T의 모든 속성을 읽기 전용으로 만든다.

type ReadonlyPerson = Readonly<Person>;
const person: ReadonlyPerson = { name: "Mimi", age: 28 };
// person.name = "Bob"; // 에러: 속성 'name'은 읽기 전용

5. Record<K, T>

Record 유틸리티 타입은 키 K와 값(타입) T에 대한 객체를 생성한다. Record의 일반적인 사용 사례는 열거형(enum) 또는 문자열을 키로 사용하여 일련의 값에 이름을 부여하는 것이다. Record를 사용하면 일련의 키-값 쌍을 가지는 타입을 정의할 때 편리하며, 특히 열거형과 함께 사용하면 코드를 더 읽기 쉽게 만들 수 있다.

//type Record<K extends keyof any, T> = {
//  [P in K]: T;
//};
// K: 객체의 키 타입을 나타내는 제네릭 매개변수. 일반적으로 문자열, 숫자 또는 열거형 타입 사용
// T: 키에 상응하는 값을 나타내는 제네릭 매개변수.

type Fruit = "apple" | "banana" | "orange"; // 문자열 리터럴 유니온 타입
type FruitPrices = Record<Fruit, number>;

// 각 과일에 대한 가격을 나타내는(저장하는) 객체 생성
const fruitPrices: FruitPrices = {
  apple: 1,
  banana: 0.5,
  orange: 0.75,
};

console.log(fruitPrices.apple); // 1.0
console.log(fruitPrices.banana); // 0.5
console.log(fruitPrices.orange); // 0.75

// 존재하지 않는 과일 접근시 에러 발생
// console.log(fruitPrices.grape); // 에러: 속성 'grape'은(는) 'Fruit'에 없음

6. Omit<T, K>

Omit은 유틸리티 타입은 제네릭 타입 T에서 지정된 키 K를 제외한 모든 속성을 가지는 타입을 생성한다. 또한 객체의 키를 기준으로 속성을 제외할 때 사용된다. Omit은 객체의 속성을 기준으로 타입을 조작하는데 사용되고 특히 객체 타입의 일부 속성을 제거하고자 할 때 유용하다. 

type PersonWithoutAge = Omit<Person, "age">;
const personWithoutAge: PersonWithoutAge = { name: "David" }; // age 속성 제외

7. Pick<T, K>

Pick은 주어진 객체 타입에서 특정 속성(키)만 선택하여 새로운 타입을 생성하는데 사용되고 객체의 일부 속성만 사용하며 다른 속성은 제거하고자 할 때 유용하다. Pick은 코드에서 필요한 정보만 추출하여 사용하고자 할 때 특히 유용하고 코드의 타입 안정성을 높이고 불필요한 데이터 유출을 방지하는 데 도움이 된다.

// Pick<T, K>
// T: 속성을 선택할 기존 타입
// K: 선택할 속성(키)을 나타내는 문자열 리터럴 유니온 타입

type Person = {
  name: string;
  age: number;
  address: string;
};

// Pick을 사용해 Person 타입에서 name과 age 속성만 선택하여 새로운 타입을 생성
type PersonInfo = Pick<Person, "name" | "age">;

// PersonInfo 타입은 name과 age 속성만 포함, 다른 속성은 포함되지 않음
const person: PersonInfo = {
  name: "Mimi",
  age: 28,
};

// address 속성은 사용할 수 없음
// person.address = "123 Main St"; // 에러: 'address' 속성은 'PersonInfo'에 없음

8. Exclude<T, U>

Exclude는 제외할 타입을 명시하여 주어진 유니온 타입에서 특정 타입을 제외하고자 할 때 사용된다. Exclude를 사용하면 코드에서 원치 않는 타입을 제거하여 더 정확한 타입을 만들 수 있다.

// Exclude<T, U>
// T: 원래의 타입(유니온 타입)
// U: T에서 제외하고자 하는 타입

type Animal = "dog" | "cat" | "bird" | "fish";

// "bird"와 "fish"를 제외한 나머지 동물을 나타내는 타입 생성
type MammalOrReptile = Exclude<Animal, "bird" | "fish">;

const pet: MammalOrReptile = "dog"; // OK
// "bird"와 "fish"는 사용할 수 없음
// const bird: MammalOrReptile = "bird"; // 에러: 'bird' 타입은 'MammalOrReptile'에 없음

 

반응형

'개발🌐 > TypeScript' 카테고리의 다른 글

230822 TypeScript: 제네릭  (0) 2023.08.22
230817 TypeScript: class  (0) 2023.08.15
230815 TypeScript: 리터럴, 유니온, 교차 Type  (0) 2023.08.15
230815 TypeScript: 함수  (0) 2023.08.15
230811 TypeScript: Interface  (0) 2023.08.11