예를 들어, 상자에 물건을 담는 일을 한다고 생각해보자. 각기 다른 종류의 물건들이 있을 때, 각 물건을 담기 위해 상자의 크기나 형태를 매번 바꾸는 것은 비효율적이다.
여기서 '상자'가 제네릭에 해당하며, '물건'이 여러 종류의 타입이라고 생각할 수 있다. 제네릭을 사용하면, 다양한 물건들(타입들)을 담을 수 있는 '일반적인' 상자를 만들 수 있다. 이 상자는 물건(타입)에 따라 그 크기나 형태가 유연하게 변할 수 있다.
function wrapInArray<T>(value: T): T[] {
return [value];
}
여기서 는 제네릭 타입을 나타낸다.
이 코드는 "어떤 타입(T)의 값을 받아서, 그 타입의 배열을 반환한다"는 의미를 가진다.
이 함수는 숫자, 문자열, 객체 등 어떤 타입의 값이든 받아서 배열로 만들 수 있다.
숫자를 넣으면 숫자 배열을 반환한다:
wrapInArray(5); // [5]
문자열을 넣으면 문자열 배열을 반환한다:
wrapInArray("hello"); // ["hello"]
제네릭은 인터페이스에도 사용할 수 있다.
예를 들어, 다양한 타입을 가질 수 있는 '결과' 객체를 정의하고 싶다면, 다음과 같이 할 수 있다.
interface Result<T> {
value: T;
error: string | null;
}
여기서 Result 인터페이스는 어떤 타입의 value를 가지고 있을 수 있으며, 오류 메시지를 위한 error 필드도 가지고 있다.
이렇게 하면, 숫자 결과, 문자열 결과 등 다양한 타입의 결과를 하나의 인터페이스로 처리할 수 있다.
function useGenericState<T>(initialState: T): [T, (newState: T) => void] {
const [state, setState] = useState<T>(initialState);
return [state, setState];
}
// 사용 예
const [count, setCount] = useGenericState(0);
const [name, setName] = useGenericState("");
여기서 useGenericState 함수는 초기 상태를 받아 현재 상태와 상태를 업데이트하는 함수를 배열로 반환한다. 이 훅은 숫자, 문자열, 객체 등 어떤 타입의 상태에도 사용할 수 있다.