NEST.js

NEST Typescript 심화 타입 ( Utility, Generic)

늘곰's 2023. 9. 29. 13:06

제네릭을 쓰는이유 

내가만든 함수의 타입을 지정할때 다른사람이 사용하거나 내가 다시 사용할 경우 

어떤 타입을 써야하는지 알수없음

그럼 any를 쓰면되지만 any 를 쓰면 아무 타입이나 전부 허용하고 무슨타입인지 구분이 되지않음

이러면 타입스크립트를 쓰는 의미가 없어짐

그래서 아무 타입이나 전부 사용 할 수 있지만 타입의 구분이 가능한 Generic을 사

 

Generic 타입

// 문자 / 숫자 /불린 기본타입

// 1. 문자/숫자/불린 기본타입
const getPrimitive = (arg1: string, arg2: number, arg3: boolean): [boolean, number, string] => {
  return [arg3, arg2, arg1];
};

const result = getPrimitive("철수", 123, true);

//
//
//2 . any 타입
const getAny = (arg1: any, arg2: any, arg3: any): [any, any, any] => {
  console.log(arg1 + 100); //any 는 아무거나 다됨
  return [arg3, arg2, arg1];
};

const result = getAny("철수", 123, true);

//
//
// 3. unknown 타입
const getUnknown = (arg1: unknown, arg2: unknown, arg3: unknown): [unknown, unknown, unknown] => {
  if (typeof arg1 === "number") console.log(arg1 + 100); // unknown 은 if 문으로 별도로 지정해줘야함
  return [arg3, arg2, arg1];
};

const result = getUnknown("철수", 123, true);

//
//
//4. generic 타입
function getGeneric<Mytype1, Mytype2, Mytype3>(arg1: Mytype1, arg2: Mytype2, arg3: Mytype3): [Mytype3, Mytype2, Mytype1] {
  return [arg3, arg2, arg1];  // any 와 다르게 타입이 예측이 됨
}
getGeneric 뒤에 타입을 명시해주면 명시한 타입 이외는 오류가 남
const result = getGeneric<string, number, boolean>("철수", 123, true);

//
//
//4. generic 타입 -2
function getGeneric2<t1, t2, t3>(arg1: t1, arg2: t2, arg3: t3): [t3, t2, t1] {
  return [arg3, arg2, arg1];
}
// getGeneric 뒤에 타입을 명시해주면 명시한 타입 이외는 오류가 남
const result = getGeneric2<string, number, boolean>("철수", 123, true);

//
//
//4. generic 타입 -3
function forRoot<t>(arg1: t): [t] {
  return [arg1];
}
// getGeneric 뒤에 타입을 명시해주면 명시한 타입 이외는 오류가 남
const result = forRoot<ApolloDriverConfig>({...});

//
//
//4. generic 타입 -4
const getGeneric4 = <t, u, v>(arg1: t, arg2: u, arg3: v): [v, u, t] => {
  return [arg3, arg2, arg1];
};
// getGeneric 뒤에 타입을 명시해주면 명시한 타입 이외는 오류가 남
const result = getGeneric4<string, number, boolean>("철수", 123, true);

Utility 타입

//Iprofile 이라는 프로필을 만들었는데
// 어떤 경우에서는 hobby 가 반드시 필요한 경우가 생김
// 이럴경우에 이런식으로 복사해서 만들어주면 되지만
// 코드가 너무 비효율적일 뿐아니라 name 같은 항목이 수정되면 코드 전체를 다 바꿔야함
// interface Iprofile2 {
//   name: string;
//   age: number;
//   school: string;
//   hobby: string;
// }

interface Iprofile {
  name: string;
  age: number;
  school: string;
  hobby?: string;
}

//1. Partial 타입
// aaa 타입은 전부 ? 가 붙은 타입이 됨 (전부 안적어도되는 타입으로 )
type aaa = Partial<Iprofile>;

//2. Required 타입
// bbb 타입은 전부 필수로 작성해아하는 타입이 됨
type bbb = Required<Iprofile>;

//3. Pick 타입
// ccc 타입은 내가 고른 타입만 필수로 작성 해야 되는 타입
type ccc = Pick<Iprofile, "name" | "age">;

//4. Omit 타입
/// ddd  타입은 제외하는 타입빼고 전부 필수
type ddd = Omit<Iprofile, "school">;

//5. Record 타입
type eee = "철수" | "영희" | "훈이"; // Union 타입

//let child1: eee = "맹구"; //여기는 유니온에 지정한 철수 영희 훈이 말고는 안됨  맹구 x
let child2: string = "사과"; // 유니온 뿐만 아니라 문자열이면 전부 다됨

type fff = Record<eee, Iprofile>; // Record 타입
// fff = {
//   철수 :  Iprofile
//   영희 :  Iprofile
//   훈이 :  Iprofile
// }

//6 객체의 key 들로 Union 타입 만들기
type ggg = keyof Iprofile; // ggg = "name" | "age" | "school" | " hobby"
let myprofile: ggg = "hobby"; //

//7. type vs interface 의 차이
//interface 는 선언 병합 가능 (같은 이름의 타입을 만들면 병합이 됨)
// type 은 안됨
interface Iprofile {
  candy: number; // 선언병합으로 추가됨
}

// 캔디만 넣었을때 에러가 나는것은
// 병합된 name age school 이 없기때문 (hobby 는 필수가아님)
// 해결법1은 안에 name age school 를넣어주던가
//해결법2는  name age school 가 필수가 아니게 만들어주면됨 (Partial 붙여주면 됨)
// let profile: Iprofile = {
//   candy: 10,

// };

//  해결법2
let profile: Partial<Iprofile> = {
  candy: 10,
};