파라미터와 리턴의 타입을 지정 가능
파라미터명: 타입 으로 정의함수명(): 리턴타입 으로 정의// JavaScript에서 함수 정의 방법
function sum(a, b) {
return a + b;
}
// TypeScript에서의 함수 정의 방법
// 파라미터의 타입과 리턴 타입을 정의
function sumTS(a: number, b: number): number {
return a + b;
}
// 화살표 함수도 아래처럼 타입 정의 가능
const add = (a: number, b: number): number => a + b;
파라미터명 뒤에 ? 를 붙여 정의
function print(name = 'Hong', age?: number): void {
console.log(`name: ${name}`);
console.log(`age: ${age}`);
}
print('둘리', 40);
print('또치');
Required Parameter가 Optional Parameter보다 후순위로 작성되면 에러 발생
// Error: A required parameter cannot follow an optional parameter.
function print(name = 'Hong', age?: number, hands: string): void {
console.log(`name: ${name}`);
console.log(`age: ${age}`);
console.log(`hands: ${hands}`);
}
파라미터의 타입에 맞추어 배열 타입으로 정의
// 여러 number 타입의 값을 받는 경우 아래와 같이 number[] 타입으로 정의
function sumAll(...numbers: number[]) {
return numbers.reduce((acc, val) => {
return acc += val;
});
}
sumAll(1, 2, 3);
함수 타입을 타입 별칭과 함께 별도로 정의
// 아래와 같이 두개의 number 타입 파라미터와 리턴 타입이 number인 공통 타입을 갖는 함수
const add = (a: number, b: number): number => a + b;
const sub = (a: number, b: number): number => a - b;
const multi = (a: number, b: number): number => a * b;
const div = (a: number, b: number): number => a / b;
// 다음과 같이 함수 타입 표현식으로 정의 가능
type Operation = (a: number, b: number) => number;
const addEx: Operation = (a, b) => a + b;
const subEx: Operation = (a, b) => a - b;
const multiEx: Operation = (a, b) => a * b;
const divEx: Operation = (a, b) => a / b;
함수도 객체라는 점을 이용하여, 객체 정의 안에 함수의 형태를 기술하는 방식
주로 함수에 추가적인 프로퍼티가 있을 때 유용
type Animal = {
(name: string): void; // 호출 시그니처
age: number; // 함수에 붙은 추가 속성
};
const human: Animal = (name) => console.log(name);
human.age = 20;
리턴 타입: 업캐스팅일 때 호환 가능
// 파라미터 타입 호환
type FncA = (num: number) => number;
type FncB = (num: number) => 10;
let fncA: FncA = (num) => num;
let fncB: FncB = (num) => 10;
// 리턴 타입이 다운캐스팅(좁은 타입 → 넓은 타입) 상황이므로 호환 가능
fncA = fncB;
// 리턴 타입이 업캐스팅(넓은 타입 → 좁은 타입) 상황이므로 에러 발생
fncB = fncA; // Error: Type 'FncA' is not assignable to type 'FncB'. Type 'number' is not assignable to type '10'.
파라미터 타입: 다운캐스팅일 때 호환 가능
// ---------------------------
// 파라미터의 갯수가 같은 경우
// ---------------------------
type FncA = (num: number) => void;
type FncB = (num: 10) => void;
let fncA: FncA = (num) => console.log(num);
let fncB: FncB = (num) => console.log(num);
// 파라미터가 다운캐스팅(좁은 타입 → 넓은 타입) 상황이므로 에러 발생
fncA = fncB; // Error: Type 'FncB' is not assignable to type 'FncA'. Types of parameters 'num' and 'num' are incompatible. Type 'number' is not assignable to type '10'.
// 파라미터가 업캐스팅(넓은 타입 → 좁은 타입) 상황이므로 호환 가능
fncB = fncA;
// ---------------------------
// 파라미터의 갯수가 다른 경우
// ---------------------------
type FncC = (name: string) => void;
type FncD = (name: string, age: number) => void;
let fncC: FncC = (name) => {};
let fncD: FncD = (name, age) => {};
// 파라미터가 다운캐스팅(좁은 타입 → 넓은 타입) 상황이므로 에러 발생
fncC = fncD; // Error: Type 'FncD' is not assignable to type 'FncC'. Target signature provides too few arguments. Expected 2 or more, but got 1.
// 파라미터가 업캐스팅(넓은 타입 → 좁은 타입) 상황이므로 호환 가능
fncD = fncC;
오버로드 시그니처: 구현부 없이 선언부만 만들어둔 함수 (복수 정의 가능)구현 시그니처: 구현부를 정의하는 함수 (단 하나만 정의)// ---------------------------
// 오버로드 시그니처
// ---------------------------
function add(a: number, b: number): number;
function add(a: number, b: number, c: number, d: number): number;
// ---------------------------
// 구현 시그니처
// ---------------------------
// 타입 좁히기를 통해 모든 오버로드 시그니처를 구현해줄 것
// 오버로드 시그니처에서 공통적으로 가지는 파라미터는 필수 파라미터로,
// 그렇지 않은 파라미터는 선택적 파라미터로 정의
function add(a: number, b: number, c?: number, d?: number): number {
if(typeof c === 'number' && typeof d === 'number') {
return a + b + c + d;
} else {
return a + b;
}
}
add(1, 2); // 정상
add(1, 2, 3, 4); // 정상
// 파라미터가 3개인 시그니처는 정의하지 않았으므로 에러 발생
add(1, 2, 3); // Error: No overload expects 3 arguments, but overloads do exist that expect either 2 or 4 arguments.
is 키워드를 활용해 런타임 검사를 통해 타입을 좁히는 방법