매개변수 a는 T 타입이고, R<T> 타입은 T가 string이든 아니든 T 타입이 됩니다. 변수 b는 R<T> 타입으로 표기했으니 T 타입인 매개변수 a를 대입할 수 있어야 합니다. 그런데 여기서도 문제가 발생합니다.
여기서 문제는 R<T> 타입이 T가 될 거라고 생각하는 것입니다. 타입스크립트는 제네릭이 들어 있는 컨디셔널 타입을 판단할 때 값의 판단을 뒤로 미룹니다. 즉, 변수 b에 매개변수 a를 대입할 때까지도 타입스크립트는 R<T>가 T라는 것을 알지 못합니다. 그래서 T를 R<T>에 대입할 수 없다는 에러가 발생하는 것입니다.
따라서 이때도 타입스크립트가 판단을 뒤로 미루지 못하도록 배열로 제네릭을 감싸면 됩니다.
function test<T extends ([T] extends [string] ? string : never)>(a: T) {
type R<T> = [T] extends [string] ? T : T;
const b: R<T> = a;
}
제네릭에 제약을 거는 부분이 복잡해졌는데, 타입 매개변수를 선언할 때 바로 <[T] extends [string]>하는 것이 불가능하므로 한 번 더 컨디셔널 타입으로 묶어 선언한 것입니다.
컨디셔널 타입은 추후 infer를 배우면 더 강력하게 사용할 수 있습니다(이 내용은 2.22절에서 배웁니다).