Typescript Utility 타입

승훈·2023년 4월 28일
0

// * Partial 파셜 타입은 특정 타입의 부분 집합을 만족하는 타입을 정의할 수 있습니다
interface Profile {
name: string,
age: number,
married: boolean
}

type PartialVar = {
[key in keyof T]?: T[key];
}

const pyo: Profile = {
name: 'pyo',
age: 27,
married: false,
}

const pyo2: PartialVar = {
name: 'pyo',
age: 27
}

// * Pick
type PickVar<T, S extends keyof T> = {
[Key in S]: T[Key];
}

const p3: PickVar<Profile, 'name' | 'age'> = {
name: 'pyo',
age: 27
}

const pyo3: Pick<Profile, 'name' | 'age'> = {
name: 'pyo',
age: 27
}

// * Omit
const pyo4: Omit<Profile, 'married'> = {
name: 'pyo',
age: 27
}

type ex = Exclude<keyof Profile, 'married'>

type O<T,S extends keyof any> = Pick<T, Exclude<keyof T, S>>

const pyo5: Pick<Profile, Exclude<keyof Profile, 'married'>> = {
name: 'pyo',
age: 27
}
const pyo6: O<Profile, 'married'> = {
name: 'pyo',
age: 27
}

type CustomExtract<T, U> = T extends U ? T : never;
type CustomExclude<T, U> = T extends U ? never : T;

// * Exclude & Extract
type Animal = 'cat' | 'dog' | 'rabbit'

type twoLeg = CustomExtract<Animal, 'rabbit'>
type fourLeg = CustomExclude<Animal, 'rabbit'>

let rabbit: twoLeg = 'rabbit';
let cat: fourLeg = 'cat';

// * Required ... 전부 필수로 만들고 싶을때
interface Profile2 {
name?: string,
age?: number,
married?: boolean
}

// -? 는 ?를 뺴고 가져와라
type CustomRequired = {
[Key in keyof T]-?: T[Key];
}

const pyo7: CustomRequired = {
name: 'pyo',
age: 27,
married: false,
}

// * readonly
interface Profile3 {
readonly name: string,
readonly age: number,
readonly married: boolean
}

// -readonly 는 readonly를 빼고 가져와라
type CustomReadonly = {
-readonly [Key in keyof T]: T[Key]
}
const pyo8: CustomReadonly = {
name: 'pyo',
age: 27,
married: false,
}
pyo8.married = true;

// Record
/
인덱스 시그니쳐를 사용하여 type 생성
인덱스 시그니쳐의 key값은 'string' | 'number' | 'symbol' | 'Template literal' 타입만 허용

*/
type userInfoType = "height" | "weight" | "age";

type humanInfo = {
[key in userInfoType]?: number
}

// P in k : 'in'을 사용하는 이유 'K'는 Template literal 타입 데이터가 들어올 수 있기 때문에
type CustomRecord<K extends keyof any, T> = {

[P in K]: T;

};
type RecordHumanInfo = CustomRecord<userInfoType, number>

let human: humanInfo = {
'age': 20
}
let human2: RecordHumanInfo = {
'height': 160,
'weight': 65,
'age': 20
}

// * NonNullable ... null, undefind 제외시킴
type M = string | null | undefined;

type N = T extends null | undefined ? never : T;
type NN = NonNullable;
type NNN = N;

// * infer .. extends 구문에만 사용가능.. 타입 추론
// (1 예제)
function zip(x: number, y: string, z: boolean): {x: number, y: string, z: boolean} {
return {x, y, z};
}
// Parameters 함수 타입 T의 매개변수 타입들의 튜플 타입을 구성합니다.
// type ttt = [number, string, boolean];
// type P<T extends (...args: ttt) => any> = T extends (...args: infer S) => any ? S : never;
type P<T extends (...args: any) => any> = T extends (...args: infer S) => any ? S : never; // 함수의 매개변수 타입을 타입화 === Parameters
type _P<T extends (...args: any) => any> = T extends (...args: any) => infer S ? S : never; // 함수의 리턴 타입을 타입화

type Params = P; // [number, string, boolean]
type First = Params[0]; // number

type _Params = _P;
let _a: _Params = {
x: 5,
y: '5',
z: true
}

// (2 예제)
const p11 = Promise.resolve(1).then((a) => a + 1).then((a) => a.toString());
const p12 = Promise.resolve(2);
const p13 = new Promise((res, rej) => {
setTimeout(res, 1000);
});

Promise.all([p11,p12,p13]).then((re) => {
console.log(re);
});

// cf 'keyof' 'typeof'
/
'typeof' : 객체를 객체 타입으로 변환
'keyof' : 객체 타입 or 인터페이스의 속성을 모아 union 타입으로 변환
/

const ODirection = {
Up: 0,
Down: 1,
Left: 2,
Right: 3,
} as const;

console.log(ODirection.Right); // 3

type R = keyof typeof ODirection;

// 객체를 타입으로 사용하기 위해선 typeof 와 keyof 파라미터를 사용해야 한다
type Direction = typeof ODirection[keyof typeof ODirection];
function run(dir: Direction) {
console.log(dir);
}

run(ODirection.Right); // 3

0개의 댓글