Typescript

[Typescript] 제네릭의 타입 제한

joy_lee 2022. 7. 13. 17:51

제네릭을 사용하면 여러 타입의 입력값을 처리할 수 있다. 하지만 타입이 명시되지 않아서 API를 사용할 수 없는 단점도 존재한다. 이런 상황에서 제네릭으로 입력받을 타입에 대한 힌트를 줄 수 있다.

 

제네릭의 타입 제한

1
2
3
4
5
6
7
8
9
10
// 제네릭의 타입 제한
// T[] : T타입 요소들이 들어간 array임을 명시
// 타입에 대한 힌트를 제공
function logTextLength<T>(text: T[]): T[] {
    // 타입제한으로 .length가 가능해진다
    console.log(text.length);
    return text;
}
 
logTextLength<string>(['h''i']);
cs

함수를 호출할 떼 제네릭으로 string을 전달하면, string[]타입을 입력받을 것이라는 힌트를 줄 수 있다.

그러면 함수 내부에서 array의 메소드인 .length를 사용할 수 있다.

 

T[]를 사용하지 않고 string[]을 입력받을 수도 있다. 하지만 함수 내부에서 API를 사용할 수 없다.

1
2
3
4
5
6
function logTextLength2<T>(text: T): T {
    // console.log(text.length); error
    return text;
}
 
logTextLength2<string[]>(['h''i']); // 입력은 가능함
cs

 

정의된 타입을 이용해 제네릭 제한하기

이미 정의된 타입을 이용해 제네릭을 제한할 수 있다.

이 때는 extends를 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 제네릭 타입 제한 2 - 정의된 타입 이용하기
interface LengthType {
    length: number;
}
 
// 인터페이스가 가진 하위 타입을 가지는 것들을 입력받는다고 명시함
function logTextLength<extends LengthType>(text: T): T {
    text.length;
    return text;
}
 
logTextLength('a'); // string.length
logTextLength([123]) // array.length
logTextLength({ length10 }) // 하위 속성으로 length 가지고 있기 때문에 입력 가능
logTextLength(10); // 오류 : number.length 없음
cs

이렇게 제네릭을 제한하면, extends 뒤의 하위타입을 함수 안에서 접근해 사용할 수 있다.

 

<T extends { toString: Function }> 으로 하위타입을 직접 명시할 수도 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
interface DropdownItem<T> {
  value: T;
  selected: boolean;
}
 
// <T extends { toString: Function }>
// toString이라는 함수 메소드를 가진 타입만 제네릭으로 받는다고 명시할 수 있다
function createDropdownItem<extends { toString: Function }>(item: DropdownItem<T>) {
  const option = document.createElement('option');
  // item.value.toString() 사용 가능
  option.value = item.value.toString();
  option.innerText = item.value.toString();
  option.selected = item.selected;
  return option;
}
cs

 

keyof 를 사용해 제네릭을 제한하기

keyof를 사용하면 keyof 다음에 오는 인터페이스가 가진 키들만 입력을 받게 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 제네릭의 타입 제한 3 - keyof
interface ShoppingItem {
    name: string;
    price: number;
    stock: number;
}
// ShoppingItem이 가진 키들 중 한 가지가 제네릭이 된다
function getShoppingItemOption<extends keyof ShoppingItem>(itemOption: T): T {
    var item: ShoppingItem = {
      name"tumbler",
      price: 12000,
      stock: 10
    }
    console.log(item[itemOption]);
    return itemOption;
}
// getShoppingItemOption(10); // 불가능
// ctrl + space로 넘길 수 있는 인자 확인 가능
getShoppingItemOption('price'); // 12000
cs

위의 경우에는 ShoppingItem의 키인 'name', 'price', 'stock'만 입력할 수 있다. typeof를 사용하지만 하위 항목의 타입과는 관련이 없다.

console.log(typeof getShoppingItemOption('price')); // 'string'

 

 

참고한 사이트

https://joshua1988.github.io/ts/guide/generics.html#%EC%A0%9C%EB%84%A4%EB%A6%AD-generics-%EC%9D%98-%EC%82%AC%EC%A0%84%EC%A0%81-%EC%A0%95%EC%9D%98

 

제네릭 | 타입스크립트 핸드북

제네릭(Generics)의 사전적 정의 제네릭은 C#, Java 등의 언어에서 재사용성이 높은 컴포넌트를 만들 때 자주 활용되는 특징입니다. 특히, 한가지 타입보다 여러 가지 타입에서 동작하는 컴포넌트를

joshua1988.github.io

 

강의

https://www.inflearn.com/course/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9E%85%EB%AC%B8/dashboard

 

타입스크립트 입문 - 기초부터 실전까지 - 인프런 | 강의

타입스크립트를 시작하는 분들을 위한 강의입니다. 최신 자바스크립트 문법을 모르는 분들도 쉽게 배울 수 있도록 교과 과정을 구성하였습니다. 어렵게만 느껴지는 타입스크립트를 입문자 관

www.inflearn.com