Variance(변성)는 합성 타입의 서브타이핑이 그 구성 요소의 서브타이핑과 어떻게 관련되는지를 기술합니다 — 즉, Container<Sub>가 언제 Container<Super>에 대입 가능한가입니다.
Dog이 Animal의 서브타입이라고 합시다.
Covariance — 방향을 보존 (직관적인 경우)
: [] = [];
: [] = dogs;
Variance(변성)는 합성 타입의 서브타이핑이 그 구성 요소의 서브타이핑과 어떻게 관련되는지를 기술합니다 — 즉, Container<Sub>가 언제 Container<Super>에 대입 가능한가입니다.
Dog이 Animal의 서브타입이라고 합시다.
: [] = [];
: [] = dogs;
주니어부터 시니어까지 상세한 답변이 포함된 IT 면접 질문 라이브러리.
후원하기반환 타입과 배열은 covariant(공변)입니다: Dog ⊆ Animal이면 Dog[] ⊆ Animal[]입니다. Dog을 반환하는 함수는 Animal을 반환하는 함수가 기대되는 곳에서 사용 가능합니다.
type Handler<T> = (arg: T) => void;
let animalHandler: Handler<Animal> = (a) => {};
let dogHandler: Handler<Dog> = animalHandler; // ✅ (strictFunctionTypes에서)
// 어떤 Animal이든 받는 핸들러는 Dog도 안전하게 처리할 수 있음
함수 매개변수는 contravariant(반공변)입니다: Handler<Animal>은 Handler<Dog>에 대입 가능하며, 이는 요소 관계의 역입니다. 이는 건전합니다 — 모든 동물을 처리하는 것은 분명히 개도 처리합니다.
// TS에서 메서드 매개변수는 기본적으로 bivariant (알려진 건전하지 않은 편의)
interface Comparer<T> { compare(a: T): void; }
TypeScript는 strictFunctionTypes에서만 독립 함수 타입을 contravariant하게 검사합니다. 메서드 매개변수는 편의를 위해 의도적으로 bivariant(양변)이며, 이는 기술적으로 건전하지 않습니다.
Variance는 왜 특정 대입이 허용되거나 거부되는지를 설명합니다 — 왜 Dog[]는 Animal[]에 맞는데 (d: Dog) => void 콜백은 (a: Animal) => void를 항상 대신할 수는 없는지를요.
이를 이해하면 generic API(예: 읽기 전용 vs 쓰기 위치)를 설계하고, 함수와 generic이 관련된 헷갈리는 "not assignable" 오류를 해독하는 데 도움이 됩니다.