
함수 타입의 호환성이란 특정 함수 타입을 다른 함수 타입으로 취급해도 괜찮은지 판단하는 것을 의미한다.

A의 반환값 타입은 Number, B의 반환값 타입은 Number Literal이므로 변수 a에 b를 할당하는 것은 가능하나 반대로는 불가능 하다.
type C = (value: number) => void;
type D = (value: number) => void;
let c: C = (value) => {};
let d: D = (value) => {};
c = d; // ✅
d = c; // ✅
type C = (value: number) => void;
type D = (value: 10) => void;
let c: C = (value) => {};
let d: D = (value) => {};
c = d; // ❌
d = c; // ✅

c매개변수의 타입은 Number, D매개변수의 타입은 Number Literal이다.
따라서, C매개변수의 타입이 D매개변수의 슈퍼타입이므로 D를 C로 취급하는 것은 불가능하나 반대로는 가능아다.
이는 반환값 타입과 반대되며 마치 다운캐스팅을 허용하는 것 같아 보인다.
이렇게 되는 이유는 두 함수의 매개변수의 타입이 모두 객체 타입일 때 좀 더 두드러진다.
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; // ✅

animalFunc에 dogFunc를 할당하는 것을 불가능하며 그 반대로는 가능하다. dogFunc의 매개변수 타입이 animalFunc의 매개변수 타입보다 작은 서브타입이기 때문이다.
animalFunc = dogFunc를 코드로 표현해보면 다음과 같다.

textFunc 타입의 매개변수 타입은 Animal이다.
그러나 함수 내부에서는 name 프로퍼티뿐 아니라 Dog타입에만 존재하는 color 프로퍼티에도 접근하려고 하기 때문에 animalFunc = dogFunc는 불가능한 것이다.
반대로 dogFunc = animalFunc를 코드로 표현하면 다음과 같다.

textFunc2 타입의 매개변수 타입은 Dog이다.
그리고 함수 내부에서는 Dog타입에도 존재하는 name 프로퍼티에만 접근하며, 이 코드는 안전하다고 볼 수 있다.
따라서, 두 개의 함수 타입 C와 D가 있을 때 두 매개변수의 개수가 같을 경우 D를 C로 취급하려면 C매개변수의 타입이 D 매개변수 타입의 서브타입이어야 한다.
매개변수의 개수가 다를 때에는 비교적 간단하다.
할당하려고 하는쪽의 함수(오른쪽)의 타입의 매개변수가 더 적을때에만 호환이 된다고 생각하면 된다.
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; // ❌