함수 타입 호환성이란 특정 함수 타입을 다른 함수 타입으로 캐스팅해도 되는지를 판단하는 것입니다.
두 가지 기준으로 함수 타입 호환성을 판단하게 됩니다.
type A = () => number;
type B = () => 10;
let a: A = () => 10;
let b: B = () => 10;
a = b; // ✅
b = a; // ❌
A
와 B
의 함수 타입이 있을 때 A
의 반환값 타입이 B
의 반환값 타입의 슈퍼 타입이라면 두 타입은 호환된다고 할 수 있습니다.
매개변수의 타입이 호환되는지 판단하는 유형은 두 가지가 있습니다.
type C = (value: number) => void;
type D = (value: 10) => void;
let c: C = (value) => {};
let d: D = (value) => {};
c = d; // ❌
d = c; // ✅
매개변수의 갯수가 같을 때 C
의 매개변수 타입이 D
의 매개변수 타입의 서브타입이어야 호환된다고 판단합니다.
다운캐스팅을 허용하는 것 같이 보입니다.
이는 매개변수의 타입이 객체타입일 경우를 생각하면 쉽습니다.
type Animal = {
name: string;
};
type Dog = {
name: string;
color: string;
};
let animalFunc = (animal: Animal) => {
console.log(animal.name);
};
let dogFunc = (dog: Dog) => {
console.log(dog.name);
console.log(dog.color);
};
animalFunc = dogFunc; // ❌
dogFunc = animalFunc; // ✅
Animal
타입은 name
프로퍼티를 포함하는 모든 객체를 의미합니다.
Dog
타입은 name
과 color
프로퍼티를 포함하는 모든 객체를 의미합니다.
이때 animalFunc = dogFunc
은 코드로 표현해보면 다음과 같습니다.
let animalFunc = (animal: Animal) => {
console.log(animal.name); // ✅
console.log(animal.color); // ❌
};
Animal
타입은 color
프로퍼티는 포함하지 않는 객체입니다. 따라서 위 코드는 불가능합니다.
이런 문제로 인하여 매개변수의 갯수가 같을 때 dogFunc
을 animalFunc
으로 취급하기 위해서는 animalFunc
의 매개변수가 dogFunc
의 매개변수의 하위 타입이어야 합니다.
type Func1 = (a: number, b: number) => void;
type Func2 = (a: number) => void;
let func1: Func1 = (a, b) => {};
let func2: Func2 = (a) => {};
func1 = func2; // ✅
func2 = func1; // ❌
매개변수의 갯수가 다를 때는 간단합니다.
매개변수의 갯수가 더 많은 함수 타입이 슈퍼 타입이므로 func1 = func2
는 업캐스팅이기 때문에 허용됩니다.
하지만 매개변수의 갯수가 다를 때는 당연히 매개변수의 타입이 동일해야 합니다.