"infer는 조건부 타입의 패턴 안에서 ‘이 자리에 있던 타입을 이름 붙여 줘’라고 말해."
타입 수준의 구조 분해
T extends Array<infer E> ? E : never는 T가 배열 모양인지 확인하고, 맞다면 원소 자리에 있던 타입을 E라는 이름으로 붙잡아 결과로 돌려줘. 값의 구조 분해처럼 타입의 모양에서 필요한 조각을 꺼내는 기능이야.
infer는 조건부 타입의 extends 패턴 안에서만 사용할 수 있어. 독립적으로 새 타입 변수를 선언하는 문법이 아니라 ‘이 패턴이 맞을 때 이 부분을 추론하라’는 표시야.
자주 쓰는 네 패턴
배열의 원소는 T extends (infer E)[], 함수의 반환값은 F extends (...args: any[]) => infer R, Promise가 풀어 낸 값은 T extends Promise<infer V>, 함수의 전체 매개변수는 F extends (...args: infer P)로 꺼낼 수 있어.
ReturnType, Parameters, Awaited 같은 표준 유틸리티가 이미 이 일을 해 주므로 앱 코드에서 직접 다시 만들 필요는 적어. 하지만 문법을 읽을 수 있어야 라이브러리 정의가 무엇을 계산하는지 이해할 수 있다.
FirstArg<F>처럼 함수의 첫 매개변수 자리에 infer A를 놓아 타입을 꺼낼 수 있어. infer가 없으면 ‘이 모양인가?’라는 yes/no 검사만 가능하지만, infer가 있으면 맞은 모양 안의 타입을 새 이름에 묶어 참 분기에서 사용할 수 있어.