TypeScript 4.2의 Leading/Middle Rest Elements in Tuple Types
문제 상황
프로젝트에서 로깅 유틸리티를 만드는 중이었다. 타임스탬프, 로그 레벨은 고정이고 나머지는 가변 인자로 받아야 했는데, TypeScript 4.1까지는 튜플의 rest element가 마지막에만 올 수 있어서 타입 정의가 불가능했다.
// 원하는 형태였지만 4.1에서는 불가능
type LogArgs = [timestamp: string, level: string, ...messages: any[]];
TypeScript 4.2 업데이트
2월에 릴리즈된 4.2에서 rest element를 튜플의 앞이나 중간에도 배치할 수 있게 됐다. 바로 프로젝트를 4.2로 올렸다.
// 이제 가능해진 패턴들
type LogArgs = [timestamp: string, ...messages: any[], level: string];
type Middleware = [...args: any[], next: () => void];
function log(...args: LogArgs) {
const [timestamp, ...rest] = args;
const level = rest.pop();
console.log(`[${timestamp}] [${level}]`, ...rest);
}
실전 활용
API 미들웨어 체인 타입을 정의할 때 특히 유용했다. 앞쪽 파라미터는 고정하고 마지막만 next 함수로 제한하는 식의 타입 안전성을 확보할 수 있었다.
type MiddlewareArgs<T extends any[] = []> =
[req: Request, res: Response, ...custom: T, next: NextFunction];
const authMiddleware = (
...args: MiddlewareArgs<[token: string]>
) => {
const [req, res, token, next] = args;
// 타입 추론 완벽하게 동작
};
가변 인자 함수의 타입 안전성이 크게 개선됐다. 사소해 보이지만 실무에서는 꽤 자주 마주치는 패턴이라 만족스러운 업데이트였다.