"T가 무엇이든 될 수 있어도 함수가 쓰려는 속성만큼은 갖춰야 해. 제약은 그 최소선을 말해."
제약 없는 T는 아직 모르는 타입
제네릭 매개변수 T에 아무 제약이 없으면 함수 몸에서는 T의 속성을 함부로 읽을 수 없어. 숫자일 수도, null일 수도, 함수일 수도 있기 때문이야. x.length를 쓰고 싶다면 length가 있다는 사실을 계약에 넣어야 해.
T extends { length: number }라고 적으면 문자열, 배열, length 속성을 가진 사용자 객체가 모두 들어올 수 있어. 클래스 상속을 요구하는 것이 아니라 해당 구조에 대입 가능해야 한다는 뜻이야.
K extends keyof T
가장 자주 만나는 제약 가운데 하나는 K extends keyof T야. K는 T에 실제로 존재하는 키만 될 수 있고 반환 타입을 T[K]로 적으면 선택한 속성의 정확한 값 타입까지 이어져. 문자열 키를 아무거나 받는 함수와 달리 오타를 컴파일 단계에서 막아.
제약은 T를 특정 타입으로 바꾸지 않고 최소 능력만 요구해 구체 타입 정보를 보존해. 생성자 계약을 받으면 new C()로 인스턴스를 만들 수 있고, get<T, K extends keyof T>(obj, key)는 실제 객체의 키만 허용하면서 반환값을 T[K]로 연결해. 제약과 호출 자리 추론이 함께 작동하는 대표 패턴이야.
함수 몸에서 사용하는 최소 멤버만 제약에 적고, 나머지 구체 정보는 T가 보존하게 해.