Lsiron
Type Script 의 Generic 이란? 본문
Generic 이란?
TypeScript에서 제네릭(generic)은 타입을 변수처럼 다룰 수 있게 해주는 강력한 기능이다. 제네릭을 사용하면 함수, 클래스, 인터페이스 등을 다양한 타입에 대해 재사용할 수 있다.
제네릭은 타입 변수를 사용하여 정의된다. 타입 변수는 보통 T, U, V 등과 같은 이름으로 명명되며, 함수나 클래스, 인터페이스에 특정 타입이 아닌 다양한 타입을 사용할 수 있도록 한다.
제네릭을 사용하는 이유
- 재사용성: 여러 타입에 대해 동일한 로직을 적용할 수 있다.
- 타입 안전성: 런타임에 타입 오류가 발생하는 것을 방지할 수 있다.
- 가독성: 코드의 의도를 명확히 하고, 타입에 대한 제약 조건을 명시할 수 있다.
제네릭 사용법
제네릭함수 사용법은 파라미터로 타입을 입력하는 함수 이기 때문에 아래와 같이 함수에 사용할 땐, 함수 우측 <> 안에 파라미터를 지정해 주고 사용할 땐 함수명 우측 <> 안에 타입을 입력하면 된다.
function iron<T>(x: T[]) :T {
return x[0];
}
let a = iron<number>([1,2])
let b = iron<string>(['lsiron', 'siron'])
타입이 필요한 곳에는 어디든지 제네릭함수를 적용 할 수 있다. 위 예시의 경우 타입 파라미터를 T로 넣어주었다.
그러면 이 함수를 사용할 때 함수명과 인자 사이에 있는 <> 에 타입만 입력 해 주면 함수의 타입을 즉석으로 정하여 사용할 수 있는 것이다.
변수 a의 경우 number 타입을 모든 T에 넣어달라는 의미이고 변수 b의 경우 string 타입을 모든 T에 넣어달라는 의미이다.
참고로 위 변수처럼 number, string으로 타입 파라미터를 지정 해 주지 않아도 자동으로 타입을 유추한 뒤, 적용시켜준다.
function iron<T>(x: T[]) :T {
return x[0];
}
let a = iron([1,2]) // number로 적용함
let b = iron(['lsiron', 'siron']) // string으로 적용함
그래도 명시적으로 타입 파라미터를 표시 해 주는 것이 좋다.
타입 파라미터 제한
function iron<T>(x: T) :T {
return x + 1; // 에러 발생!!!
}
let a = iron<number>(100)
위 예시의 함수를 보자.
x + 1 을 return 하기 때문에 이는 수학연산을 사용하고 있다. 이 수학연산은 number 타입에만 가능하다.
즉, 에러가 발생하는 이유는 T 파라미터를 넣어줄 때, number로 확정 지어주지 않았기 때문이다. 이로 인해 함수 자체에서 에러가 발생한 것이다.
이러한 에러가 발생하지 않도록 하기 위해, T 파라미터 에는 number 타입만 들어올 수 있게 Narrowing을 해 주어야 한다.
이때 제네릭 함수에서 타입파라미터에 제한을 두는 방법은 바로 extends를 사용하는 것이다.
function iron<T extends number>(x: T) :T {
return x + 1;
}
let a = iron<number>(100)
console.log(a) // 101 출력
이제 extends로 인해 T 파라미터는 number 타입으로 제한이 된다. T 파라미터가 number 속성을 가지고 있는지 체크 하는 것이다.
( interface와 class에서 사용하던 extends 처럼 복사의 개념이 아니라 체크의 개념이다. )
참고로 이 extends는 응용하여 사용 될 수 있다.
extends 우측에는 number, string 처럼 반드시 정해진 타입만 들어 오는 것이 아니라 interface, type alias 등을 넣어 줄 수 있다.
interface LengthCheck {
length : number
}
function iron<T extends LengthCheck>(x: T) :T {
return x.length;
}
let a = iron<string>('100')
console.log(a) // 3 출력
string이나 array 같은 경우 .length를 붙일 수 있기 때문에 에러가 발생하지 않는다.
함수에서의 제네릭
다음은 제네릭을 사용하여 여러 타입에 대해 동작할 수 있는 함수를 정의하는 예시이다.
function identity<T>(arg: T): T {
return arg;
}
let number = identity<number>(42); // T는 number로 추론됨
let text = identity<string>("Hello, TypeScript!"); // T는 string으로 추론됨
이 예시에서 identity 함수는 인수의 타입과 동일한 타입을 반환한다. T는 타입 변수로, 호출 시점에 타입을 지정할 수 있다.
클래스에서의 제네릭
제네릭을 사용하여 다양한 타입의 데이터를 처리할 수 있는 클래스를 정의할 수도 있다.
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
constructor(zeroValue: T, add: (x: T, y: T) => T) {
this.zeroValue = zeroValue;
this.add = add;
}
}
let myNumber = new GenericNumber<number>(0, (x, y) => x + y);
console.log(myNumber.add(myNumber.zeroValue, 5)); // 5
여기서 GenericNumber 클래스는 숫자 타입뿐만 아니라 다른 타입에도 사용할 수 있다.
인터페이스에서의 제네릭
인터페이스에서도 제네릭을 사용할 수 있다.
interface Pair<T, U> {
first: T;
second: U;
}
let numberStringPair: Pair<number, string> = {
first: 1,
second: "one"
};
console.log(numberStringPair);
Pair 인터페이스는 두 개의 타입 T와 U를 받아 각각 first와 second에 할당한다.
참조 : 코딩애플
'언어 > Type Script' 카테고리의 다른 글
Type Script 에서 외부 자바스크립트 파일을 사용할 때 (declare, ambient module / local module) (0) | 2024.07.17 |
---|---|
Type Script 의 tuple type 이란? (0) | 2024.07.17 |
Type Script 에서의 export , import 그리고 namespace (0) | 2024.07.16 |
Type Script 의 protected 와 static (1) | 2024.07.16 |
Type Script 의 public 과 private (1) | 2024.07.16 |