
함수를 설명하는 가장 좋은 방법
function func(a: number, b: number): number {
return a + b;
}
const add = (a: number, b: number): number => a + b;
function introduce(name = "제노", tall: number) {
console.log(`name: ${name}`);
console.log(`tall: ${tall}`);
}
introduce("제노", 175);
기본값을 string을 넣어줘서 string으로 추론함
function introduce(name = "제노", tall?: number) {
console.log(`name: ${name}`);
console.log(`tall: ${tall}`);
}
introduce("제노");
tall 매개변수가 인수로 전달하지 않아서 오류 발생, 생략하고 싶다면 tall?:
// ...연산자: 가변 길이의 매개변수를 전달하면 배열로 묶어주는 js 문법
function getSum(...rest: number[]) {
let sum = 0;
rest.forEach((it) => (sum += it));
}
getSum(1, 2, 3); // 6
이전 강의에서는 다음과 같이 타입을 정의했었다.
const add = (a: number, b: number): number => a + b;
⇒ 타입 별칭을 통해 함수의 타입을 정의할 수 있다.
type Add = (a: number, b: number) => number;
const add: Add = (a, b) => a + b;
type Operation = (a: number, b: number) => number;
const add: Operation = (a, b) => a + b;
const sub: Operation = (a, b) => a - b;
const multiply: Operation = (a, b) => a * b;
const divide: Operation = (a, b) => a / b;
type Operation2 = {
(a: number, b: number): number;
};
type Operation2 = {
(a: number, b: number): number;
};
const add2: Operation2 = (a, b) => a + b;
const sub2: Operation2 = (a, b) => a - b;
const multiply2: Operation2 = (a, b) => a * b;
const divide2: Operation2 = (a, b) => a / b;
⇒ 특정 함수 타입을 다른 함수 타입으로 취급해도 괜찮은가를 판단하는 의미
type A = () => number;
type B = () => 10;
let a: A = () => 10;
let b: B = () => 10;
a = b;
// number 리터럴 타입을 number 타입으로 취급하겠다는 것은
// 업캐스팅이므로 호환 가능하다.
b = a; // 반대는 허용이 안됌
b = a가 호환되지 않는 이유
a의 타입은 number, b는 number 리터럴 타입이다
number를 number 리터럴로 취급하겠다는 것은 다운 캐스팅이므로 호환이 되지 않는 것이다.
⇒ 즉, 반환값끼리 다운 캐스팅이 되면 안된다.
2-1. 매개변수의 개수가 같을 때
type C = (value: number) => void;
type D = (value: number) => void;
let c: C = (value) => {};
let d: D = (value) => {};
c = d;
d = c;
위 코드에서는 매개변수의 개수가 같고, 타입도 같다.
양쪽으로 다 호환이 가능하다.
호환이 되지 않는 경우
type C = (value: number) => void;
type D = (value: 10) => void;
let c: C = (value) => {};
let d: D = (value) => {};
c = d
// d 타입이 number가 아닌 number 리터럴이면 오류가 발생한다.
// 즉, d 타입을 c타입으로 취급하겠다는 것.
// number 리터럴 타입을 => number 타입으로 취급하겠다는 것은 업캐스팅
// 근데 오류가 발생
// 매개변수의 타입을 기준으로 호환성을 판단할 때는 반대로
// 업캐스팅일 때는 호환이 안된다고 평가함
d = c
// c 타입을 d 타입으로 취급하겠다는 것
// c는 number타입, d는 number 리터럴 타입
// 이는 다운캐스팅이다.
// 매개변수의 호환성을 판단할 때는 다운캐스팅을 호환할 수 있도록 한다.
type Animal = {
name: string;
};
type Dog = {
name: string;
color: string;
};
let animalFunc = (animal: Animal) => {
console.log(animal.name);
};
let dogFunc = (dog: Dog) => {
console.log(dog.name);
console.log(dog.color);
};
animalFunc = dogFunc; // 호환이 안된다.
// animalFunc 타입이 슈퍼타입이며 업캐스팅이 일어난다.
dogFunc = animalFunc;
let testFunc = (animal: Animal) => {
console.log(animal.name);
console.log(animal.color); // animal에는 프로퍼티가 없음
// 이런 말도 안되는 코드가 나올 수 있기 때문에,
// 다운캐스팅을 허용하는 것임
};
let testFun2 = (dog: Dog) => {
console.log(dog.name); // 호환 가능
console.log(dog.color); // 호환 가능
};
⇒ 즉, 정리하자면 매개변수 기준으로 호환성을 따질 때는, 다운 캐스팅만 호환이 된다는 것이다.
2-2. 매개변수의 개수가 다를 때
type Func1 = (a: number, b: number) => void;
type Func2 = (a: number) => void;
let func1: Func1 = (a, b) => {};
let func2: Func2 = (a) => {};
func1 = func2;
func2 = func1; // 호환 불가
// func1 매개변수 갯수는 2개, func2는 1개
// func1(2개) <- func2(1개)
// 매개변수가 다를 때는 할당하려고 하는 쪽의 함수의 타입의
// 매개변수의 갯수가 더 적을 때만 호환이 된다.
// 또한 타입이 같은 매개변수가 있어야 한다.