TL;DR


엄격 모드 비엄격 모드
함수 리턴 타입 공변적 공변적
함수 파라미터 타입 반공변적 이변적
그 외 공변적 공변적

공변성 | Covariance


공변성 : AB의 서브 타입이면, T<A>T<B>의 서브 타입

아래 예시에서 superArray(string | number)는 subArray(string)보다 넓은 타입을 가진다. 따라서 stringstring | number에 포함되는 서브 타입이고, string | numberstring을 포함하는 슈퍼 타입이다.

좁은 타입인 subArray를 넓은 타입인 superArray에 대입하는건 문제가 발생하지 않는다. 반면 넓은 타입을 좁은 타입에 대입할 땐 에러가 발생한다.

let superArray: Array<string | number> = [];
let subArray: Array<string> = [];

superArray = subArray; // OK
subArray = superArray; // Error 'number' 형식은 'string' 형식에 할당할 수 없습니다(ts2322)

이처럼 좁은 타입을 넓은 타입에 대입 할 수 있는 동작을 공변성(Covariance; 协方差)이라고 부른다. 타입스크립트는 기본적으로 공변성을 갖는다.

함수의 리턴 타입 역시 공변성을 가진다. a의 리턴 타입(number)이 B의 리턴 타입(number | string)보다 좁은 타입이므로, ab에 대입해도 문제가 발생하지 않는다.

function a(x: string): number { return 0; }
type B = (x: string) => number | string;
const b: B = a; // OK (a 리턴 타입 < B 리턴 타입)

반대로 a 리턴 타입이 더 넓은 타입을 갖도록 변경하면 에러가 발생한다.

function a(x: string): number | string { return 0; }
type B = (x: string) => number;
const b: B = a; // Error (a 리턴 타입 > B 리턴 타입)

반공변성 | Contravariance


<aside> 💡 함수 파라미터는 strictFunctionTypes 옵션을 켰을 땐(true) 반공변성을, 해당 옵션을 껐을 땐(false) 이변성을 가진다. strictFunctionTypes 옵션의 기본값은 true이다.

</aside>

반공변성 : AB의 서브 타입이면, T<B>T<A>의 서브 타입