tanstack query 오픈소스 코드를 보다가 신기해 보이는 유틸리티 타입이 있었습니다.
export type NoInfer<T> = [T][T extends any ? 0 : never]
이 타입은 TypeScript 5.4 버전에 배포됐다고 하는데요! 어떤 경우에 사용하는 타입일까요?
먼저 다음 예시를 봅시다. 배열에서 특정 요소의 첫 번째 인덱스를 반환하는 간단한 함수입니다.
코드를 실행하면, d는 배열에 존재하지 않으므로 -1를 반환합니다.
const func = <T extends string>(array: T[], searchElement: T) => {
return array.indexOf(searchElement);
};
func(['a', 'b', 'c'], 'd'); // 에러 발생 x
여기서 array와 searchElement가 제네릭 타입을 추론하는데 사용됩니다. 그래서, 제네릭 타입은 'a' | 'b' | 'c' | 'd'
로 추론됩니다.
만약, 두 번째 인수로 array 배열의 요소만 받고 싶다면 어떻게 하면 좋을까요?
func(['a', 'b', 'c'], 'a'); // 에러 x
func(['a', 'b', 'c'], 'd'); // 에러 발생
NoInfer가 등장하기 전에는, 첫 번째 제네릭 타입의 하위 타입인 제네릭 타입을 추가하여 해결했다고 합니다.
const func = <T extends string, C extends T>(array: T[], searchElement: C) => {
return array.indexOf(searchElement);
};
func(['a', 'b', 'c'], 'a'); // 에러 x
func(['a', 'b', 'c'], 'd'); // 에러 발생
TypeScript 5.4부터는 NoInfer 타입을 활용해 훨씬 깔끔한 해결이 가능합니다.
const func = <T extends string>(array: T[], searchElement: NoInfer<T>) => {
return array.indexOf(searchElement);
};
NoInfer는 불필요한 타입 추론을 방지하여 원하는 타입 안정성을 더 쉽고 명확하게 유지할 수 있도록 도와줍니다. 앞으로 잘 활용해보면 좋을 것 같네요!
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html#the-noinfer-utility-type
https://kimjeongwonn.com/2024/NoInfer-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0
https://dev.to/makoto0825/noinfer-in-typescript-54-4k72