기본 타입들을 다루면서 함수 호환성에 대한 이야기를 했었습니다. 기억이나지 않으실 분들을 위해 다시 소개를 하자면 A
와 B
타입이 있을때, A를 B로 취급해도 괜찮은지 확인하고 사용해도 괜찮다면 호환이 되는 것이다라고 했었습니다.
그리고 지난 포스트에서 매개변수와 반환값을 통해 함수도 타입을 갖고 있다고 했었습니다. 그렇다면 함수 사이에도 호환성이라는 개념이 당연히 존재하겠죠?
이번 포스트에서는 함수 사이에서 호환성을 어떤 기준으로 판별하는지에 대해 알아보도록 하겠습니다.
함수 호환성
도 기본 타입 호환성과 다를 것이 없습니다
A 함수와 B 함수가 있을때 A함수를 B함수로 취급해도 괜찮은지 판단하는 것입니다. 역시 사용해도 괜찮다고 판단되면 호환이 된다라고 알게됩니다.
함수의 호환성은 매개변수와 반환값을 가지고 판단하게 됩니다.
매개변수
를 이용해서 함수 호환성을 판단할 경우엔 먼저 매개변수의 개수를 확인합니다. 그리고 개수가 같은지 다른지에 따라 동작이 달라지게 됩니다.
매개변수의 개수가 같을 때는 A 함수의 매개변수 타입이 B 함수 매개변수의 자식 타입일 경우에 호환이 가능합니다.
좀 더 가독성이 좋도록 함수 타입 표현식을 사용해서 함수를 표현했습니다.
type A = (x: number) => number;
type B = (x: 1) => number;
let a: A = x => x + 1;
let b: B = x => x + 1;
a = b; //Error!!!
b = a;
number 리터럴 타입이 number 타입의 자식이기 때문에 B 함수는 A 함수로 취급될 수 없으나 그 반대로는 호환이 가능합니다.
A 함수의 매개변수로는 B 함수의 리터럴 매개변수인
1
을 포함해서 다양한 number 타입이 올 수 있습니다. 따라서 A 함수를 B 함수로 취급하는 것에는 아무런 문제가 발생하지 않습니다.그러나 B는 오직
1
만을 매개변수로 받을 수 있기 때문에 B 함수를 A 함수로 취급할 수 없습니다.
매개변수의 개수가 다를 경우에는 매개변수가 더 많은 쪽으로 호환성을 판단하게 됩니다.
type A = (x: number, y: number) => number;
type B = (x: number) => number;
let a: A = (x, y) => x + y;
let b: B = x => x + 1;
a = b;
b = a; //Error!!!
이에 따라 A 함수보다 매개변수 수가 적은 B 함수는 A 함수로 취급될 수 있으나 그 반대로는 매개변수 개수가 초과되므로 호환이 불가능합니다.
반환값을 기준으로 함수 호환성을 판단할 경우는 간단합니다.
A 함수 반환값 타입이 B 함수 반환값 타입의 부모 타입이면 B 타입은 A 타입에 호환됩니다.
type A = () => number;
type B = () => 1;
let a: A = () => 1;
let b: B = () => 1;
a = b;
b = a; //Error
따라서 B 함수는 A 함수에 호환 될 수 있지만, 그 반대 상황에서는 호환되지 않습니다.