백구의 코딩찌개
  • [TYPE SCRIPT] 타입 스크립트 Generic
    2023년 12월 31일 10시 00분 32초에 업로드 된 글입니다.
    작성자: 코딩백구
    반응형

    Generic 이란?

    • Generic 은 C#, Java 등의 정적 타입 언어의 경우, 함수 또는 클래스를 정의하는 시점에서 리턴 타입이나 매개변수의 타입을 선언해줘야하는데, 같은 함수여도 매개변수 타입과 리턴 타입이 다른 경우가 있다면 그에 해당하는 함수를 하나하나 다 작성해줘야 합니다.
    • 이때, 재사용성이 높은 컴포넌트를 만들어 하나의 함수만으로 사용하고 싶을 때 자주 사용하는 기능이 바로 Generic 입니다.
    • Generic 을 사용하면 단일 타입이 아니라 사용하고 싶을 때 마다 그에 맞는 타입으로 사용할 수 있어서 코드를 일일이 작성할 필요가 사라져 코드의 가독성 또한 향상됩니다.

    Generic 사용 방법

    • Generic 을 사용하기 위해서는 변수명, 함수명 뒤에다가 <T> 를 작성해줍니다. (꼭 T 가 아니어도 되지만, 일반적으로는 Type 을 의미한다는 뜻에서 T 로 작성합니다.)
    function getSize<T>(arr: T[]): T {
    // T 라는 어떤 타입을 받아서 이 함수에서 사용할 수 있게 해준다.
    	return arr.length;
    }
    
    const arr1 = [1, 2, 3];
    
    console.log(getSize(arr1));
    
    const newArr = ["1", "2", "3"];
    
    console.log(getSize(newArr));
    // 자동으로 매개변수의 타입을 추론해서 넣어준다.
    // 속성값의 타입을 동적으로 주고 싶을 때
    
    interface Mobile2<T> {
    	name: string;
    	price: number;
    	option: T;
    }
    
    const m1: Mobile2<object> = {
    	name: "s21",
    	price: 1000,
    	option: {
    		color: "red",
    		coupon: false,
    	},
    };
    
    const m2: Mobile2<string> = {
    	name: "s20",
    	price: 800,
    	option: "good",
    };
    
    // extends
    interface User4 {
    	name: string;
    	age: number;
    }
    
    interface Car4 {
    	name: string;
    	color: string;
    }
    
    interface Book {
    	price: number;
    }
    
    const user4: User4 = {
    	name: "a",
    	age: 20,
    };
    
    const car4: Car4 = {
    	name: "bmw",
    	color: "black",
    	};
    
    const book: Book = { price: 10000 };
    
    function showName4<T extends { name: string }>(data: T): string {
    // 그냥 <T>만 하게되면 T의 타입에 name 이 있는지 없는지 확신할 수 없어서 에러가 뜬다.
    // 이 때, T extends 를 사용하게 되면 data 타입으로 T 가 오는데 이것은
    	{name: string} 를 확장한 형태이다 라고 알려주는 역할이다.
    // --> T 는 항상 {name: string} 를 갖고 있는 객체만 받을 수 있다.
    	return data.name;
    }
    
    showName4(user4);
    
    showName4(car4);
    
    // showName4(book) // 에러가 뜬다.

    Generic 이 사용되는 Utility Types

    • Utility Type 이란, 이미 정의한 타입을 다른 타입으로 변환할 때 사용하는 문법입니다.
    • 하나하나씩 살펴보도록 하겠습니다.

    1. keyof

    • keyof 를 사용하면 key 값들을 모두 유니언 형태로 받습니다.
    interface User5 {
    	id: number;
    	name: string;
    	age: number;
    	gender: "m" | "f";
    }
    
    // 여기서 keyof 키워드를 사용하면 User5 의 key값들을 유니언 형태로 받을 수 있다.
    type UserKey = keyof User5; // 'id' | 'name' | 'age' | 'gender'
    
    const uk: UserKey = "id";

    2. Partial<T>

    • Partial 은 프로퍼티를 모두 Optional 로 바꿔줍니다.
    interface User5 {
    	id: number;
    	name: string;
    	age: number;
    	gender: "m" | "f";
    }
    // 프로퍼티를 모두 옵셔널로 바꿔준다.
    // Partial<User5> 를 해주게 되면
    // interface User5{
    // id?: number
    // name?: string
    // age?: number
    // gender?: 'm' | 'f'
    // } 과 같다.
    
    let admin: Partial<User5> = {
    	id: 1,
    	name: "Bob",
    };

    3. Required<T>

    • Partial 과 반대로 프로퍼티를 모두 필수 요소로 바꿔줍니다.

    4. Readonly<T>

    • 프로퍼티를 모두 readonly 로 바꿔줍니다.

    5. Record<K,T>

    • 여기서 K 는 Key 이고, T는 Type 을 의미합니다.
    interface Score1 {
    	"1": "A" | "B" | "C" | "D";
    	"2": "A" | "B" | "C" | "D";
    	"3": "A" | "B" | "C" | "D";
    	"4": "A" | "B" | "C" | "D";
    }
    
    const score: Score1 = {
    	"1": "A",
    	"2": "B",
    	"3": "C",
    	"4": "D",
    };
    
    // 이렇게 작성 가능
    const score1: Record<"1" | "2" | "3" | "4", "A" | "B" | "C" | "D"> = {
    	"1": "A",
    	"2": "B",
    	"3": "C",
    	"4": "D",
    };
    
    // 이렇게도 가능
    type Grade2 = "1" | "2" | "3" | "4";
    type Score2 = "A" | "B" | "C" | "D";
    
    const score2: Record<Grade2, Score2> = {
    	"1": "A",
    	"2": "C",
    	"3": "B",
    	"4": "D",
    };
    
    // 다른 예시
    interface User6 {
    	id: number;
    	name: string;
    	age: number;
    }
    
    function isValid(user: User6) {
    	const result: Record<keyof User6, boolean> = {
    	id: user.id > 0,
    	name: user.name !== "",
    	age: user.age > 0,
    	};
    	
    	return result;
    }
    // 해당하는 key 와 type 만 올 수 있다.

    6. Pick<T,K>

    • T 타입에서 K 프로퍼티만 골라서 사용
    interface User7 {
    	id: number;
    	name: string;
    	age: number;
    	gender: "M" | "W";
    }
    
    const admin2: Pick<User7, "id" | "name"> = {
    	id: 3,
    	name: "jin",
    };

    7. Omit<T,K>

    • T 타입에서 K 프로퍼티만 생략해서 사용
    interface User7 {
    	id: number;
    	name: string;
    	age: number;
    	gender: "M" | "W";
    }
    
    const admin3: Omit<User7, 'gender' | 'age'> = {
    	id: 3,
    	name: 'jin'
    }

    8. Exclude<T1, T2>

    • T1 에서 T2 를 제외하고 사용
    type T1 = string | number | boolean
    
    type T2 = Exclude<T1, number | string> // boolean 만 남게 된다.

    9. NonNullable<Types>

    • null 과 undefined 를 제외한 타입을 생성
    type T3 = string | null | undefined | void;
    
    type T4 = NonNullable<T3> // string | void 만 남는다.
    반응형
    댓글