과거 프로그래밍 자료들/Javascript&typescript
[TS] 공변성, 반공변성, 오버로딩
평부
2022. 9. 18. 14:13
출처 : https://github.com/ZeroCho/ts-all-in-one
* 공변성, 반공변성, 이변성, 불변성
▶ 함수 간에 서로 대입할 수 있냐, 없냐 여부
* 리턴값은 더 넓은 타입이면 대입 가능
* 매개변수는 더 좁은 타입이면 대입 가능
//해당 코드는 가능
function a(x: string | number): number {
return +x;
}
a('1'); //1
type B = (x: string) => string | number;
const b: B = a;
* 리턴값
//리턴값 예시
function a(x: string): number {
return +x;
}
a('1'); //1
type B = (x: string) => number | string;
const b: B = a;
//a는 string 받아서 number 리턴
//B는 string 받아서 number 또는 string 리턴
//서로 타입이 다름 허나 대입이 됨 => ?
//오류 나는 경우
function a(x: string): number | string {//(x: string) => string 또는 (x: string) => number 가능
return +x;
}
a('1'); //1
type B = (x: string) => number; //(x: string) => string도 되는데 type B에는 불가능
const b: B = a;
* 매개변수
//매개변수
function a(x: string | number): number {
return +x;
}
a('1'); //1
type B = (x: string) => number;
const b: B = a;
//매개변수는 string | number을 하나로 보고 좁은 타입으로 대입 가능(리턴값이랑 반대)
//오히려 넓은 타입으로는 대입 불가
//오류 나는 경우
function a(x: string): number {
return +x;
}
a('1'); //1
type B = (x: string | number) => number;
const b: B = a;
* 타입 넓히기, 타입가드
//타입 넓히기
//TS가 모든 상황을 고려해서 타입을 넓힘
let A = 5;
let a: string | number = 5
//타입가드 : 타입 좁히기
if (typeof a === "string") {
console.log("이건 문자열",a)
} else if (typeof a === "number") {
console.log("이건 숫자", a)
}
* 오버로딩
▶ 같은 타입을 여러 번 선언
▶ 여러 가진 상황 중 한 가지에 해당하는 것을 만들기 위함
[예시] - filter의 경우 방식 2가지 있음
filter<S extends T>(predicate: (value: T, index: number, array: readonly T[]) => value is S, thisArg?: any): S[];
혹은
filter(predicate: (value: T, index: number, array: readonly T[]) => unknown, thisArg?: any): T[];
둘 다 사용 가능
* 오버로딩 예시 1
//declare : 함수 선언만 하고 실제 코드는 다른 곳에 위치
declare function add(x: number, y: number): number
declare function add(x: number, y: number, z: number): number
add(1, 2);
add(2, 3, 4);
//한 방에 타이핑 하고 싶을 때
//(위의 코드와 같은 내용) 그럴 때 옵셔널 사용
declare function add(x: number, y: number, z?: number): number
add(1, 2);
add(2, 3, 4);
//오버로딩은 모든 케이스가 다 되도록 -> 여러 개 중 하나에 걸리게 함
declare function add(x: number, y: number): number
declare function add(x: number, y: number, z: number): number
declare function add(x: string, y: string): string
add(1, 2);
add(2, 3, 4);
add('1', '2');
* 오버로딩 예시 2
▶ 인터페이스, 클래스 안에서도 오버로딩 가능
//interface
interface Add {
(x: number, y: number): number;
(x: string, y: string): string;
}
//오버로딩 하면 실제 구현부에서는 any 사용 가능
const add: Add = (x: any, y: any) => x + y;
//class
class A {
add (x: number, y: number): number;
add (x: string, y: string): string;
//위의 두 add만 오버로딩, 아래 any는 무시됨
add(x: any, y: any) {
return x + y;
}
}
//const c: number
const c = new A().add(1, 2); //숫자면 add (x: number, y: number): number;
//const C: string
const C = new A().add('1', '2'); //문자면 add (x: string, y: string): string;