Blog

[TypeScript] 8. TypeScript의 Generics

Category
Author
citeFred
citeFred
PinOnMain
1 more property
TypeScript 기본기 다지기
Table of Content

1. Generics

새로운 폴더(metaverse/greeter/src/generics)
generics.ts
identity() 라는 함수가 다음처럼 구성되어 있다.
function identity(arg: number): number { return arg; }
TypeScript
복사
숫자 타입의 파라미터 arg 변수를 입력받아, 숫자 타입의 arg 변수를 반환
이런 함수는 왜있는가?
CLI에서 echo command에서 자주 볼 수 있음
입력된 값을 화면에 출력하는데 사용 됨
사용자가 입력한 데이터가 예상한 형식인지 확인하는 타입 검증의 목적
입력값을 다른 함수에 전달하거나, 조건문에서 사용하여 프로그램의 흐름을 제어하는 연산의 기초로 활용
사용자에게 입력한 값을 다시 보여줌으로써, 입력이 올바르게 처리되었음을 확인하기 위한 기초
만약, 다른 타입도 받을 수 있도록 하려면 어떻게 구성해야 하는가?
function identity(arg: any): any { return arg; }
TypeScript
복사
단순히, 배운 것 처럼 any 타입을 이용 할 수도 있다.
하지만 이것은 정확한 타입 검증의 목적을 달성 하기 어려울 수 있음
number 를 입력했는데 어떠한 요인에 의해서라도 변질된다면 string이 나와도 타입이 변한것을 오류로 알 수 없음
그럼 모든 타입 마다 이것을 작성해야 하는가?
이것 또한 함수의 이름이 중복되어 허용되지 않는다.
그럼 중복을 피해서 만들었다고 가정하자.
function identityNum(arg: number): number { return arg; } function identityStr(arg: string): string { return arg; } function identityBool(arg: boolean): boolean { return arg; } //... function identityObj1(arg: obj1): obj1 { return arg; } function identityObj2(arg: obj2): obj2 { return arg; } interface obj1 { //... } interface obj2 { //... } //...
TypeScript
복사
하지만 타입은 기본형 타입만 있지 않다. 객체도 타입이 될 수 있고 따라서 수없이 많은 함수를 생성해야 하게 될 것이다.
이런 비효율적인 상황을 대처하기 위한 것이 Generics이다.
< > 안에 작성된 키워드가 해당 함수에 동일한 표현들을 동적으로 통일시킨다는 것을 나타냄
통일 될 최초 타입은 키워드가 작성된 Parameter(매개변수)의 타입이 기준이 되며 해당 블록의 키워드가 포함 된 타입들은 모두 이를 따르게 됨
// Use Generics function identity<Type>(arg: Type): Type { return arg; }
TypeScript
복사
Type이란 키워드 대신 T라는 키워드로 대체하여 사용하는 경우가 많음
// Use Generics function identity<T>(arg: T): T { return arg; }
TypeScript
복사
참고 : 여기 표현된 Type 또는 T(or U or V …) 는 실제 있는 자료형(타입) 이 아니다. 자유롭게 지정 할 수 있어 타입 별칭(Type Alias)과 혼동 될 수 있지만 다른 기능
관례적으로 T를, 매개 변수가 2개 이상을 제너릭으로 표현해야 하는 경우엔 이후로는 U, V, W 등을 자주 사용한다.
function identity<T, U>(arg1: T, arg2: U): [T, U] { return [arg1, arg2]; } const result = identity(20, "Hello"); // result는 [number, string] 타입
TypeScript
복사
정확히 구분 되는지 테스트
function isNumber(value: any) { return typeof value === 'number' && !isNaN(value); } function isString(value: any) { return typeof value === 'string'; } // isArray는 Array의 내장 함수 사용 // 간단 테스트 // given const testValue1: number = 20; const testValue2: string = "Hi"; const testValue3: number[] = [1, 20]; // when 1 const numberIdentity = identity(testValue1); // number 타입 // then 1 console.log(`Input type is : ${typeof testValue1}`); console.log(`Output type is : ${typeof numberIdentity}`); console.log(`Is number: ${isNumber(numberIdentity)}`); // true // when 2 const stringIdentity = identity(testValue2); // string 타입 // then 2 console.log(`Input type is : ${typeof testValue2}`); console.log(`Output type is : ${typeof stringIdentity}`); console.log(`Is string: ${isString(stringIdentity)}`); // true // when 3 const arrayIdentity = identity(testValue3); // number[] 타입 // then 3 console.log(`Input type is : ${typeof testValue3}`); console.log(`Output type is : ${typeof arrayIdentity}`); console.log(`Is array: ${Array.isArray(arrayIdentity)}`) // true
TypeScript
복사
Generics를 사용한 identity() 함수가 예상대로 작동하는지 확인해보자.
테스트코드 작성의 Given-When-Then 패턴
준비-실행-검증의 단계로 테스트의 흐름이 명확하고, 각 단계에서 어떤 작업이 이루어지는지 쉽게 이해하기 위한 표현 기법
Given: 테스트에 필요한 초기 데이터를 설정
When: 테스트를 실행하는 부분으로, identity 함수를 호출
Then: 각 입력값에 대한 결과를 검증하고 출력
제너릭을 실제로 구현하고, 사용하기 어려울 수도 있지만, 알고 있어야 하는 이유
Array와 같은 내장 라이브러리를 살펴보자.
우리가 사용하는 많은 함수, 메서드, 라이브러리 등은 이처럼 구현되어 있기 때문에 이는 다양한 데이터 타입을 쉽게 사용 할 수 있도록 구현되어 있다.
필요에 따른 튜닝, 검토 등을 위해 내부 구조를 살펴보게 될 때 이해 할 수 있어야 한다.
Search
 | Main Page | Category |  Tags | About Me | Contact | Portfolio