| 엄격 모드 | 비엄격 모드 | |
|---|---|---|
| 함수 리턴 타입 | 공변적 | 공변적 |
| 함수 파라미터 타입 | 반공변적 | 이변적 |
| 그 외 | 공변적 | 공변적 |
strictFunctionTypes 옵션을 껐을 때 함수 파라미터 동작공변성 :
A가B의 서브 타입이면,T<A>는T<B>의 서브 타입
아래 예시에서 superArray(string | number)는 subArray(string)보다 넓은 타입을 가진다. 따라서 string은 string | number에 포함되는 서브 타입이고, string | number는 string을 포함하는 슈퍼 타입이다.
좁은 타입인 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)보다 좁은 타입이므로, a를 b에 대입해도 문제가 발생하지 않는다.
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 리턴 타입)
<aside>
💡 함수 파라미터는 strictFunctionTypes 옵션을 켰을 땐(true) 반공변성을, 해당 옵션을 껐을 땐(false) 이변성을 가진다. strictFunctionTypes 옵션의 기본값은 true이다.
</aside>
반공변성 :
A가B의 서브 타입이면,T<B>는T<A>의 서브 타입