안녕하세요 SOPT 36기 웹 YB 김예지입니다.
오늘은 공변성, 반공변성에 대해 알아보겠습니다.. 공변성반공변성이변성불변성 발음도 어렵고 이름도 어렵게 생겼습니다. 흑흑.
이 함수 타입을 다른 곳에 넣어도 될지.. 이 객체를 이 타입에 할당할 수 있을지... 이런 고민을 해보셨다면 한 번쯤 들어보셨을 거 같아요.

변성
공통으로 들어가있는 변성. 이란..
어떤 타입이 다른 타입과 할당 관계를 가질 수 있는지 판단하는 기준입니다.
타입 A가 있고 타입 B가 있을 때,
- A를 -> B에 할당 가능한지.
- B를 -> A에 할당가능한지..
이런 방향성을 기준으로 공변/반공변/이변/불변이 나뉘게 됩니다.
공변성 Convariance
자식타입을 부모 타입에 대입할 수 있다는 개념입니다.
다시 말해, 타입이 구체적일 때 상위 타입 자리에 들어갈 수 있는 것을 의미합니다.
예를 들어 아래와 같은 코드가 있다고 할 때,
type Animal = { name: string };
type Dog = { name: string; breed: string };
const dog: Dog = { name: '구름', breed: '말티즈' };
const animal: Animal = dog; // Dog → Animal (공변성)
Dog는 Animal을 포함하고 있기 때문에, 더 많은 정보를 가진 타입이 적은 정보를 가진 타입 자리에 들어갈 수 있어요. 이를 공변성이라고 합니다.
반공변성 Contravariance
부모 타입을 자식 타입에 대입할 수 있다는 개념입니다.
다시 말해, 어떤 타입이 더 일반적일 때, 하위 타입 자리에 들어갈 수 있다는 뜻입니다.
주로 함수 매개변수에서 많이 사용되는데요, 아래 코드를 보시면..
type Animal = { name: string };
type Dog = { name: string; breed: string };
const useAnimal = (a: Animal) => {
console.log(a.name);
};
const useDog: (d: Dog) => void = useAnimal; // 가능
useAnimal은 Animal을 처리하는 함수인데, 이 함수를 Dog을 처리하는 함수 자리에 넣고 있습니다.
Dog는 Animal보다 더 구체적인 타입이지만, Animal을 처리할 수 있다면 당연히 Dog도 처리할 수 있어요.
타입스크립트에서는 함수 매개변수에서 반공변을 허용합니다.
이변성 Bivariance
타입스크립트는 함수 매개변수에 대해서 엄격한 반공변이 아니라 이변성을 적용합니다. 다시 말하면, 공변성과 반공변성을 둘 다 허용하는 것을 의미합니다.
type Animal = { name: string };
type Dog = { name: string; breed: string };
type CallbackDog = (dog: Dog) => void;
const fn1: CallbackDog = (animal: Animal) => {
console.log(animal.name);
}; // 이변성
엄격하게 말하면 animal은 dog가 아닙니다. 실제로는 타입 오류 가능성이 매우 존재하지만 실용성을 위해서 의도적으로 허용하는 것입니다.
tsconfig.json에서 strictFunctionTypes: true로 설정하면 이변성은 막히고 정확한 반공변성만 허용됩니다.
{
"compilerOptions": {
"strictFunctionTypes": true
}
}
불변성 Invariance
완전히 동일한 타입만 허용하는 것을 의미합니다.
주로 배열이나 제네릭 타입에서 자주 나타납니다.
type Animal = { name: string };
type Dog = { name: string; breed: string };
const dogs: Dog[] = [{ name: '구름', breed: '말티즈' }];
const animals: Animal[] = dogs; // ❌ 오류 발생
Dog[]를 Animal[]처럼 다루면 타입 안전성이 깨질 수 있기 때문에 타입스크립트가 금지하는 것입니다.
배열과 제네릭은 불변이기 때문에 타입이 정확하게 일치해야만 대입이 가능합니다.
마무리
꽤나 생소한 단어이지만 결국 타입 간에 어떠한 방향으로 대입이 가능한가? 를 나타내는 개념인 거 같습니다.
안정적이고 오류 없는 최고 타입스크립트를 위하여~....
'4주차' 카테고리의 다른 글
| 챗지*티야 빨리 글 좀 써줘!!! (3) | 2025.05.13 |
|---|---|
| useEffect vs useLayoutEffect (0) | 2025.05.13 |
| 🛠️ React Suspense로 비동기 처리와 UX 개선하기 (0) | 2025.05.13 |
| TypeScript에서 같은 이름의 타입을 여러 개 생성하면 어떻게 될까? (0) | 2025.05.13 |
| API 폴더? 서비스 폴더? 구조 분리가 중요한 이유 (0) | 2025.05.13 |