과거 프로그래밍 자료들/Javascript&typescript

[TS] (utility types)Partial, Pick & Omit, Exclude, Extract 타입 분석

평부 2022. 9. 18. 16:19

 

 

출처 : https://github.com/ZeroCho/ts-all-in-one

 

GitHub - ZeroCho/ts-all-in-one

Contribute to ZeroCho/ts-all-in-one development by creating an account on GitHub.

github.com

 

https://github.com/microsoft/TypeScript/blob/main/lib/lib.es5.d.ts

 

GitHub - microsoft/TypeScript: TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

TypeScript is a superset of JavaScript that compiles to clean JavaScript output. - GitHub - microsoft/TypeScript: TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

github.com

 

 

* [lib.ex5.d.ts] Patial, Pick

type Partial<T> = {
    [P in keyof T]?: T[P];
};

type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
};

 

* [lib.ex5.d.ts] Omit, Exclude, Extract

▶ 타입에도 삼항연산자가 들어갈 수 있음

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
type Exclude<T, U> = T extends U ? never : T;
type Extract<T, U> = T extends U ? T : never;

//예시
type Animal = "Cat" | "Dog" | "Human"
//type Mammal = "Cat" | "Dog"
type Mammal = Exclude<Animal, "Human"> //'Cat' | 'Dog' (never은 사라짐)
//필요한 부분 추출
type Human = Extract<Animal, 'Human'> //'Cat' | 'Dog' (never은 사라짐)

 

 

[Partial 예제 - 이런 상황을 해결하는 법 : Patial 사용하기]

//매번 같은 객체를 만드는 단점 존재
interface Profile {
    name: string,
    age: number,
    married: boolean
}
//가능은 하나 중복됨
interface NewProfile {
    name: string,
    age: number,
}
const zerocho: Profile = {
    name: "zerocho",
    age: 29,
    married: false
}
//married만 빼기 애매함
const newZeroCho: NewProfile = {
    name: "zerocho",
    age: 29
}

 

 

[Partial 사용하기 예제]

interface Profile {
    name: string,
    age: number,
    married: boolean
}

const zerocho: Profile = {
    name: "zerocho",
    age: 29,
    married: false
}
//Partial : Profile을 옵셔널로 만듦
//interface Profile {
//     name?: string,
//     age?: number,
//     married?: boolean
// }

const newZeroCho: Partial<Profile> = {
    name: "zerocho",
    age: 29
}

 

 

[Partial을 P로 지정해서 직접 만들기 예제]

▶ Partial의 문제점 : Profile의 값들이 옵셔널로 되어 있어 const newZeroCho: P<Profile> = {}

이런 값도 문제 없다고 나옴

▶ Pick이나 Omit을 사용할 수 있음

//Partial을 P로 만들 수 있는가?

interface Profile {
    name: string,
    age: number,
    married: boolean
}
//value 접근 
//type Name = Profile['name'] (Profile.name이 아님)


type P<T> = {
    //어떤 객체가 오든지 그 객체의 키를 아래에 씀
    //아래의 자리에는 name, age, marreid가 옴  = 옵셔널로 만듦
    [Key in keyof T]?: T[Key];
}

//type P<T>{}와 동일한 내용
//P<Profile>
//{
	//Profile의 키를 다 꺼냄
	//name?: string,
	//age?: number,
	//married?: boolean 
//}

const zerocho: Profile = {
    name: "zerocho",
    age: 29,
    married: false
}

const newZeroCho: P<Profile> = {
    name: "zerocho",
    age: 29
}

 

 

* Pick이나 Omit 사용하는 경우

interface Profile {
    name: string,
    age: number,
    married: boolean
}

const zerocho: Profile = {
    name: "zerocho",
    age: 29,
    married: false
}

//Pick은 Profile에서 name과 age만 가져옴
const newZeroCho: Pick<Profile, 'name' | 'age'> = {
    name: "zerocho",
    age: 29
}

//Omit : Profile에서 married만 제외
const newZeroCho2: Omit<Profile, "married"> = {
    name: "zerocho",
    age: 29
}

 

 

* Pick을 직접 만드는 경우

interface Profile {
    name: string,
    age: number,
    married: boolean
}

//Pick을 직접 만듦
//S가 아무 값이나 되는 게 아닌 T랑 연관되야 함
type P<T, S extends keyof T> = {
    [Key in S]: T[Key];
}

const zerocho: Profile = {
    name: "zerocho",
    age: 29,
    married: false
}

//Pick을 P로 만듦
//제한조건인 name, age를 먼저 써야 함
const newZeroCho: P<Profile, 'name' | 'age'> = {
    name: "zerocho",
    age: 29
}

 

 

* Omit 

interface Profile {
    name: string,
    age: number,
    married: boolean
}

const zerocho: Profile = {
    name: "zerocho",
    age: 29,
    married: false
}

// type A = Exclude<keyof Profile, 'married'>

//Omit 만들기
//keyof 붙는 이유 Profile 자체가 아닌 "name" | "age" | "married"를 원하기 때문
//S의 제한조건을 붙임
type O<T, S extends keyof any> = Pick<T,  Exclude<keyof T, S>>

const newZeroCho: O<Profile, "married"> = {
    name: "zerocho",
    age: 29
}