반응형
250x250
Notice
Recent Posts
Recent Comments
Link
관리 메뉴

짧은코딩

공변성과 반공변성(함수) 본문

TS/TS(with ZeroCho)

공변성과 반공변성(함수)

5_hyun 2023. 10. 2. 03:31

어떤 함수는 다른 함수에 대입할 수 있는데, 대입이 불가능한 경우도 있다. 이를 제대로 이해하려면 공변성, 반공변성을 알아야 한다.

 

  • 공변성: A->B일 때, T<A> -> T<B> 인 경우
  • 반공변성: A->B일 때, T<B> -> T<A>인 경우
  • 이변성: A->B일 때, T<A> -> T<B>도 되고 T<B> -> T<A>도 되는 경우
  • 무공변성: A->B일 때, T<A> -> T<B>도 안 되고 T<B> -> T<A>도 안 되는 경우

TS는 기본적으로 공변성을 갖고 있지만, 함수의 매개변수는 반공변성을 갖는다!

그리고 TS Config에서 strict와 strictFunctionTypes가 모두 체크되어야 함수의 매개변수가 반공변성을 갖는다. 둘 다 체크되지 않으면 이변성을 갖는다.

반환값

a->b인 경우

function a(x: string): number {
	return 0;
}
type B = (x: string) => number | string;
let b: B = a;

a 함수를 b 타입에 대입할 수 있고, 함수 반환값은 b가 더 넓은 타입이다.

(T 타입이 함수<반환값>이면)a->b일 때, 함수 a를 타입 b에 대입할 수 있기에 T<a> -> T<b>가 된다.

즉, 함수의 반환값은 공변성을 가진다.

b->a인 경우

function a(x: string): number | string {
	return 0;
}
type B = (x: string) => number;
let b: B = a; // error

string | number를 number에 대입할 수 없다는 에러가 발생한다.

이때 strict 혹은 strictFunctionTypes를 해제해도 에러가 발생한다. 이는 반환값에 대해서는 항상 공변성을 가진다고 볼 수 있다.

매개변수

매개변수는 strict 옵션에서 반공변성을 가진다.

 

-b->a일 때

function a(x: string | number): number {
	return 0;
}
type B = (x: string) => number;
let b: B = a;

매개변수가 string -> string | number라서 b->a인 상황이다. 

그런데 a를 b에 대입할 수 있다. b->a에서 T<a> -> T<b>라서 매개변수가 반공변성을 가지고 있다.

 

-반대의 경우

function a(x: string): number {
	return 0;
}
type B = (x: string | number) => number;
let b: B = a;

반대는 불가능하다. 따라서 매개변수는 반공변성을 가진다.

하지만 strict 옵션을 해제하면 에러가 발생하지 않는다. strict 옵션을 해제하면 이변성을 가지기 때문이다.

 

-결론

매개변수는 반공변성 또는 이변성을 가진다!

객체의 메서드 타이핑에 따른 변성

아래 예시는 strict 옵션이 활성화된 상태이다.

 

interface SayMethod {
    say(a: string | number): string;
}

interface SayFunction {
    say: (a: string | number) => string;
}

interface SayCall {
    say: {
        (a: string | number): string;
    }
}

const sayFunc = (a: string) => "hello";

const MyAddingMethod:SayMethod = {
    say: sayFunc // 이변성
}

const MyAddingFunction: SayFunction = {
    say: sayFunc // 반공변성
}

const MyAddingCall: SayCall = {
    say: sayFunc // 반공변성
}

sayFunc 함수는 (a: string) => string 타입을 가진다. 매개변수 반공변성에 의해 (a: string | number) => string에 대입할 수 없다.

하지만 "함수(매개변수): 반환값"으로 선언한 것은 매개변수가 이변성을 가진다.

"함수: (매개변수) => 반환값"으로 선언한 것은 반공변성을 가진다.

728x90
반응형

'TS > TS(with ZeroCho)' 카테고리의 다른 글

브랜드 속성 & 타입 좁히기  (1) 2023.11.12
infer로 타입 추론(with 컨디셔널 타입)  (0) 2023.11.11
오버로딩(any를 써야하는 경우!)  (0) 2023.09.28
타입을 집합으로 생각하자  (0) 2023.09.15
React with TS  (0) 2022.09.12
Comments