[Typescript] 제네릭 - 함수와 인터페이스에서의 사용법
제네릭이란?
TS코드에서 타입을 함수의 파라미터처럼 사용하는 방법이다.
함수의 재사용성을 위해 타입별로 여러 함수를 만들지 않고 하나의 함수로 여러 타입의 입력값을 처리할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
// 타입을 명시하지 않을 때(any타입)
function logText(text) {
console.log(text);
return text;
}
// 반환값은
logText(100); // 숫자 10
logText('hi'); // 문자열 hi
logText(true); // 진위값 true
// 제네릭을 사용할 때 <T>
function logText2<T>(text: T): T {
console.log(text);
return text;
}
// 함수를 호출할 때, 타입도 같이 입력해야 한다.
logText2<string>('hi');
|
cs |
logText()에 숫자, 문자열, 진위값을 입력하기 위해 타입을 명시하지 않으면 any타입으로 간주한다.
logText2()에서는 제네릭을 사용해 입력값, 반환값의 타입을 입력받아 명시할 수 있다. 제네릭은 보통 T로 표시하며 다른 이름을 사용해도 상관없다.
제네릭을 사용하지 않는다면?
any타입으로 반환된 값은 API를 사용할 수 없다.
기존 타입 정의 방식으로 여러 타입의 입력값을 처리하려고 하면 함수를 중복 선언할 수 밖에 없다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 16 |
// 타입 명시를 위해 여러개 생성한 함수
function logString(text: string) {
console.log(text);
return text;
}
function logNumber(num: number) {
console.log(num);
return num;
}
// 유지보수 측면에서 좋지 않다.
const text = logString('hello');
const num = logNumber(10);
// text.trim(), num.isNaN() 등을 사용할 수 있지만... |
cs |
유니온 타입을 사용한다면?
유니온 타입을 사용한다면 여러 타입의 인자를 입력받을 수 있다.
하지만 입력에 대한 문제는 해결됐지만 반환값에 대한 문제는 해결되지 않는다.
1
2
3
4
5
6
7
8
|
// 유니온 타입 사용
function logText(text: string | number) {
console.log(text);
// 자동완성 불가능
return text;
}
const a = logText('a'); // a 의 타입은 string | number
// a.split('') 사용불가 - 타입을 정확히 알 수 없음
|
cs |
logText()를 통해 반환된 값이 string임이 분명하지만 TS에서는 구분하지 못하므로 ( string | number )로 인식해 관련된 메소드를 사용할 수 없다.
제네릭 사용
제네릭을 통해 함수 실행 시 전달받은 타입을 인자 타입과 반환 타입으로 사용하겠다고 명시할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
|
// 제네릭 사용
function logText<T>(text: T): T {
console.log(text);
return text;
}
const str = logText<string>('abc');
str.split(''); // TS에서 str이 string타입임을 알고있기 때문에 에러가 뜨지 않는다.
// 타입을 각각 선언하며 함수를 만들지 않아도 된다.
const login = logText<boolean>(true);
|
cs |
타입에 구애받지 않고 자유롭게 입력할 수 있으며, 반환값의 타입도 명시되어 이후에 관련 메소드를 사용할 수 있다.
인터페이스에 제네릭 선언
인터페이스에서도 제네릭을 사용해 항목의 타입을 정의할 수 있다.
1
2
3
4
5
6
|
// 인터페이스에 제네릭 사용
interface Dropdown<T> {
value: T;
selected: boolean;
}
const obj: Dropdown<string> = { value: 'abc', selected: false }
|
cs |
제네릭을 사용한 하나의 인터페이스로 여러가지 타입을 커버할 수 있다.
아래는 여러가지 dropdown 항목을 제네릭을 사용해 만든 코드이다.
1
2
3
4
5
6
7
8
9
10
11
|
const emails: DropdownItem<string>[] = [
{ value: 'naver.com', selected: true },
{ value: 'gmail.com', selected: false },
{ value: 'hanmail.net', selected: false },
];
const numberOfProducts: DropdownItem<number>[] = [
{ value: 1, selected: true },
{ value: 2, selected: false },
{ value: 3, selected: false },
];
|
cs |
같은 DropdownItem 인터페이스를 가지고 다른 value의 타입을 가진 객체를 생성한다.
참고한 사이트
https://joshua1988.github.io/ts/guide/generics.html
강의