inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

[리뉴얼] 타입스크립트 올인원 : Part1. 기본 문법편

공변성과 반공변성

함수의 공변성과 반공변성에 대한 이유 설명

814

raipendalk

작성한 질문수 1

7

질문은 아니지만 다른 분들도 쉽게 보시고 이해하실 수 있도록 해당 수업의 질문으로 남기도록 하겠습니다.
설명에 앞서 그냥 강사님께서 하신 말씀처럼 외우는게 제일 나을수도 있습니다. 그냥 저처럼 이해하지 못하면 못 넘어가는 사람들을 위해 남깁니다.


공변성과 반공변성에 대하여 매개변수와 리턴타입의 대입가능성에 대해 설명하고자 합니다. 강의에서 사용된 예제를 사용하겠습니다.

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

b("asdf") // B타입에 맞음 정상
b(123) //B타입에 맞지 않는 매개변수 이므로
       //typescript가 오류를 잡아줄 수 있음

먼저 매개변수에 대한 이야기입니다. 변수 b의 B 타입으로 정의되었습니다. 즉, 매개변수로는 x: string만 오도록 강제할 것입니다. 이는 b("asdf")로 사용했을 때 a("asdf")를 사용한 것과 같은 상황이니 문제가 없습니다. 하지만 반대면 어떨까요?

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

b("asdf") // 타입 B에 대해서도 정상
          //a함수가 실행될때도 정상
b(123); // B타입상으로만 보면 정상임
//그러나 실제로 a함수가 실행될 때 오류
//따라서 이런 상황이 발생하지 않도록
//타입스크립트는 타입B에 함수 a를 할당할 수 없도록 함

만약 이 상황이라면 변수 b는 B타입이기 때문에 매개변수로 number도 사용하능 합니다. 즉 타입상으로는 b(123)이 가능하다는 것이죠, 하지만 이 경우 a(123)이 실행되는 것과 같은데 a의 매개변수로는 string만 가능하기 때문에 문제가 발생합니다.

정리하자면 실제로 대입된 함수의 매개변수가 허용하지 않는 타입을 넣으면 안 되기 때문에, (대입되는 함수의 매개변수)는 (타입의 매개변수)와 같거나 더 넓어야합니다.


리턴값도 비슷한 원리입니다.

function a(x: string | number): number{
    return 0;
}
type B = (x: string) => number | string;
let b: B = a;
let result = b("asdf");
//result의 타입은 B타입에 의해 number|string 으로 추론됨
//실행결과 실제 타입은 number로 추론과 일치

타입스크립트 입장에서 b("asdf")의 예상 결과는 number | string 이겠죠. b는 타입 B 니까요. 그리고 실제로 b("asdf")는 실제로 a("asdf")를 실행하는 것과 같으니 실제로는 number가 리턴됩니다. 타입스크립트는 number | string를 예상하고 있고, 거기에 number가 온 것이니 문제가 없습니다.

반대 상황을 봅시다.

function a(x: string | number): number | string {
    return 0;
}
type B = (x: string) => number;
let b: B = a;
let result = b("asdf");
//타입 B만 보고 추론하면 result는 number임
//근데 실제 실행결과로 result는 string이 될 수도 있음

타입스크립트는 b("asdf")의 결과로 number 만을 기대할 것입니다. 근데 실제로 a("asdf")number | string 이에요. 그러면 원래는 b의 실행결과로는 number만 예상하고 있었는데 실제 결과로 number | string 이면 문제가 있겠죠?

정리하자면 실제로 대입된 함수가 리턴한 값이 타입의 리턴값에 포함되지 않으면 안 되기 때문에, (대입되는 함수의 리턴값)는 (타입의 리턴값)와 같거나 더 좁아야합니다.


위 모든 원칙은, 타입스크립트가 실제로 대입된 함수의 타입은 신경쓰지 않고, 현재 정의된 타입이 뭔지만 신경쓰기 위해서 존재한다고 생각하시면 이해가 편하실수도 있을 것 같네요...

타입스크립트의 타입검사기 입장에서 let b: B = a;이후에 b를 쓸 때, a에 대해서 신경1도 안쓰고 B에 대해서만 타입 검사를 해주려고 처음 대입할때 매개변수의 범위와 리턴값의 범위를 저렇게 제한했다고 보시면 된다는 뜻입니다.


typescript

답변 2

1

제로초(조현영)

훌륭한 분석이십니다!!

0

메가

오 덕분에 이해할 수 있었습니다! 감사합니다

데코레이터가 현재도 자주 쓰이는 문법인가요?

0

76

2

유틸리티 타입 실제로 구현은 못해도 하나씩 외우면 실무할 때 지장 없겠죠?

0

63

1

매핑 타입은 type에서밖에 안된다고 하네요?

0

62

2

자바에서의 오버로딩과 같은 개념이라고 생각해도 되나요?

0

67

2

filter 함수 반환 타입 네로잉 질문

0

65

2

map<U>(callbackfn: ....) 할때 U는 왜 여기 있는거에요??

0

44

2

ts 컴파일을 위한 type 라벨링 부분

0

44

1

concat 함수 타입 구현 중 질문 있습니다!

0

99

2

filter 메소드 질문

0

52

1

forEach 제네릭 관련 문의

0

59

1

타입 추론 시 가장 넓은 범위로 추론이 되는 건가요?

0

162

1

enum이 javascript로 트랜스파일링될때 사라진다하셨는데요

0

206

1

함수 파라미터 타입 정의 시 ...args: any[]와 ...args: any 의 차이

0

223

1

Flat type에서 ReadonlyArray 타입을 사용하는 이유?

0

156

1

bind type 질문

1

147

1

Lowercase type 관련 질문

0

151

1

key-value 타입 자동추론 질문드립니다

0

264

1

타입스크립트 교과서, p131

0

263

1

타입스크립트 교과서 p122 forEach 메서드 질문

0

231

1

타입스크립트 교과서 p116 , 코드에러남

1

268

1

타입스크립트 교과서 p112 , 코드가 안읽힙니다..

0

263

1

타입스크립트 교과서 p83

1

181

1

타입스크립트교과서 p39 쪽 코드가 이해가 안되요

1

223

1

class 에서 ts의 private vs js의 private field( # )

0

334

1