타입스크립트 제네릭 선언, 타입제한 간단 정리

 

제네릭 (Generics)

- C#, Java 등 언어에서 재사용성이 높은 컴포넌트를 만들때 활용되는 특징

- 단일 타입이 아닌 다양한 타입에서 작동하는 컴포넌트를 생성하는데 사용

- 타입을 마치 함수의 파라미터처럼 사용

 

🔵 함수에 제네릭 선언

제네릭이 아닌 유니온 타입으로 했을 때 문제점

function logMessage(text: string | number) {
    console.log(text);
    return text;
}
const res = logMessage('hi');

// string 메서드 사용
res.split(''); // ==> 에러! (string인지 number인지 몰라)

- 유니온 타입을 활용하면 최종값의 타입이 정확하지 않음

- return한 값이 여전히 string | number 타입이 되어버림!

타입스크립트 입장에서 무슨 타입이 올지 정확하지 않기 때문에 문자열 메서드나 넘버 메서드 사용 불가ㅜ

 

제네릭 문법 활용했을 때

function logMessage<T>(text: T): T {
    console.log(text);
    return text;
}

// 타입이 string 이라고 명시
const res = logMessage<string>('안녕');

// string 메서드 사용
res.split(''); // string 타입이라 OK

- T 타입을 받으면, 파라미터로 받은 text도 T 타입임을 정의

 

 

🔵 인터페이스에 제네릭 선언

- 제네릭을 사용한 하나의 인터페이스로 여러 타입을 생성할 수 있다.

 

일반 인터페이스를 사용했을 때

interface User {
    name: string;
    age: number;
}

const tay: User = { name: '테이', age: 30 };
const tay2: User = { name: '테이', age: '서른' }; // ==> 에러! age의 타입에러

 

제네릭 인터페이스를 사용했을 때

interface User<T> {
    name: string;
    age: T;
}

// age의 타입도 같이 전달
const tay: User<number> = { name: '테이', age: 30 }; // OK
const tay2: User<string> = { name: '테이', age: '서른' }; // OK

 

 

🔵 제네릭 타입 제한

- 제네릭을 사용하면 여러 타입의 입력값을 처리할 수 있다.

- 하지만 API를 사용하거나 특정 타입의 메서드를 활용하고자 할 때 타입의 범위를 제한해야한다.

(TS 입장에서는 어떤 타입이 들어올지 모르기 때문에!)

- 즉, 제네릭으로 입력 받을 타입에 대한 힌트를 주는 방법 (타입을 제한하는 방법)

 

extends 를 활용한 타입 제한

- extends 를 활용하면 확장한 타입의 자손만 제네릭 타입으로 들어올 수 있다.

 

일반 제네릭일 경우

// 일반적인 제네릭 함수
function logLength<T>(text: T): T {
	// string 메서드 사용
   	console.log(text.length); // ==> 에러! string이 안올수도있음!
    return text;
}

 

정의된 타입 이용 제네릭 (extends 활용)

interface LengthType {
    // 제한할 속성 (length는 무조건 있어야해!)
    length: number;
}

// 확장된 제네릭 함수
function LogLength<T extends LengthType>(text: T): T{
    text.length;
    return text;
}
// => length 속성이 있는 것들만 받을 수 있다.

LogTextLength('a'); // OK
LogTextLength({ length: 10 }); // OK (length가 있긴하니까)
// LogTextLength(10); ==> 에러! 숫자엔 length 속성 없음

- 확장된 제네릭 함수의 T는 LengthType을 확장하여 해당 인터페이스의 하위이니까 LengthType의 속성(length)을 가지는 것들을 입력받는다는 뜻

 

keyof 를 활용한 타입 제한

interface Uesr {
  name: string;
  age: number;
}

// User 인터페이스의 key값(name,age)를 확장
function UserOption<T extends keyof User>(item: T): T {
  return item;
}

// User 인터페이스의 key값만 받을 수 있다
UserOption('name'); // name
UserOption('age'); // age
UserOption('job'); // ==> 에러!

console.log(typeof UserOption('name')); // string

- keyof 를 활용하면 keyof 다음에 오는 인터페이스가 가진 key들만 입력받을 수 있다.

key만 받게하는 건 알겠지만, 어떻게 활용해야할 지는 감이 안온다 .. ^^;

 


참고 강의 : https://taylog.tistory.com/217

 

[강의리뷰] 실전 프로젝트로 배우는 타입스크립트 시리즈 강의 후기 (캡틴판교) 😱 타입스크립

캡틴판교 타입스크립트 시리즈 강의 후기 이번엔 타입스크립트 강의 후기입니다! 회사에서 타입스크립트를 사용할 일이 생겨서 이 전에 사둔 타입스크립트 강의를 드디어 수강완료했습니다!

taylog.tistory.com