July 6, 2024 • ☕️ 5 min read
Tip) 공변: “같이 변한다”
공변성(Covariance): A
(좁은 타입)가 B
(넓은 타입)의 서브타입이면, T<A>
는 T<B>
의 서브타입이다.
ex) 클래스 인스턴스, 함수의 반환값 (함수 파라미터를 제외한 모든 경우)
let stringArray: Array<string> = [];
let array: Array<string | number> = [];
array = stringArray; // ✅ OK - stringArray는 array를 포함
stringArray = array; // 🚨 Error
반공변성(Contravariance): A
(좁은 타입)가 B
(넓은 타입)의 서브타입이면, T<B>
는 T<A>
의 서브타입이다.
ex) 함수 파라미터
type Logger<T> = (param: T) => void;
let logNumber: Logger<number> = (param) => {
console.log(param); // number
};
let log: Logger<string | number> = (param) => {
console.log(param); // string | number
};
logNumber = log; // ✅ OK
log = logNumber; // 🚨 Error
logNumber
함수에 log
함수를 대입했을 때, log
함수는 string | number
타입의 인자를 받을 것으로 기대하기 때문에 number
타입만 받을 것으로 기대되는 함수 logNumber
에 함수 log
를 대입할 수 있다.log
함수에 logNumber
함수를 대입했을 때, log
함수의 인자 타입이 number
임을 보장할 수 없기 때문에 에러가 발생한다.이변성(Bivariance): A
가 B
의 서브타입이면, T<A>
→ T<B>
도 되고 T<B>
→ T<A>
도 되는 경우
Array
와 메서드의 관계 등에서 논리적 흐름을 보장하기 위해 함수임에도 공변성을 보장해야 하는 경우가 있기 때문에 타입스크립트는 이변성을 가진다.type Logger<T> = (param: T) => void;
let log: Logger<string | number> = (param) => {
console.log(param);
};
// ✅ OK
log = (param: string | number | boolean) => {
console.log(param);
};
// ✅ OK
log = (param: number) => {
console.log(param);
};
Tip! 누군가한테 콜스택을 넘겨줄 때는 반공변하고, 내가 콜스택을 가지고 있을 때는 공변하는 것이 안전하다
in
, out
제네릭 타입이 공변한지, 반공변한지 명시적으로 표기하는 것
타입이 output으로 사용될 때 out
, input으로 사용될 때 in
을 사용한다.
interface Animal {
animalStuff: any;
}
interface Dog extends Animal {
dogStuff: any;
}
// ...
type Getter<T> = () => T;
type Setter<T> = (value: T) => void;
type Getter<out T> = () => T;
type Setter<in T> = (value: T) => void;
둘 다 사용할 수도 있다. (이변)
interface State<in out T> {
get: () => T;
set: (value: T) => void;
}
Ref
min-content
max-content
fit-content
min-content
, 최댓값이 max-content
로, 뷰포트가 변함에 따라 쓸 수 있는 최대 범위를 사용한다.…
…
발도 다치고, 장마가 시작되고… ☔️
이른 휴가 후에 혼자 일, 공부만 열심히 하다가
반 년 동안 혼자 준비했던 JLPT 시험을 보고왔다.
어떤 문항들은 많이 쉬웠고, 어떤 문항들은 많이 어려웠다.
설마 통과하겠지? 🙃