객체의 메서드 타입을 정의하는 상황은 종종 발생한다.
객체의 메서드 타입을 정의하는 방법은 2가지가 있다.
두 방법은 얼핏 비슷해 보이지만 미묘한 차이를 가지고 있다.
interface Props<T extends string> {
onChangeA?: (selected: T) => void;
onChangeB?(selected: T): void;
}
const Component = () => {
const changeToPineApple = (selectedApple: "apple") => {
console.log("this is pine" + selectedApple);
}
return (
<Select
// Error
// onChangeA={changeToPineApple}
// OK
onChangeB={changeToPineApple}
/>
)
}
(— strict 모드에서) 부모 컴포넌트에서 매개변수가 apple일 때 실행되는 메서드를 생성했다 가정
on-ChangeA일 때는 타입 에러 발생, onChangeB일 때는 타입에러 발생 X
// 모든 유저(회원, 비회원)은 id를 갖고 있음
interface User {
id: string;
}
interface Member extends User {
nickName: string;
}
let users: Array<User> = [];
let members: Array<Member> = [];
users = members; // OK
members = users; // Error
모든 User가 id를 가지고 있으며 회원(Member)은 회원 가입 시 등록한 별명(nickName)을 추가로 갖고 있다. Member는 User를 상속하고 있는데 User보다 더 좁은 타입이자 User의 서브타입이다.
타입 A가 B의 서브타입일 때, T<A>가 T<B>의 서브타입이 된다면 공변성을 띠고 있다고 말한다.
// 모든 유저(회원, 비회원)은 id를 갖고 있음
interface User {
id: string;
}
interface Member extends User {
nickName: string;
}
type PrintUserInfo<U extends User> = (user:U) => void;
let printUser: PrintUserInfo<User> = (user) => console.log(user.id);
let printMember: PrintUserInfo<Member> = (user) => console.log(user.id, user.nickName);
printMember = printUser; //OK
printUser = printMember; // Error - Property 'nickName' is missing in type 'User'
// but required in type 'Member'