함수의 매개변수와 반환 값의 타입을 지정할 수 있습니다.
function func(a: number, b: number) {
return a + b; // func(): number (type assertion)
}
/**
* arrow function type definition
*/
const add = (a: number, b: number) => a + b; // add(): number (type assertion)
함수에 선택적 매개변수를 제공할 수도 있습니다. 이를 위해서는 매개변수 뒤에 '?'를 추가하면 됩니다. 또한 매개변수에 기본값을 설정할 수도 있습니다. 이 경우, 매개변수에 값이 제공되지 않을 경우에 사용될 값을 지정하면 됩니다. 선택적 매개변수는 항상 맨 뒤에 위치해야합니다.
function introduce(name = "이정환", age: number, tall?: number) {
console.log(`name: ${name}`);
if (typeof tall === "number"){
console.log(`tall: ${tall + 10}`);
}
}
함수에 임의의 수의 매개변수를 전달할 수 있도록 하려면 나머지 매개변수(Rset Parameter)를 사용할 수 있습니다. 이를 위해서는 매개변수 이름 앞에 '...'를 추가하면 됩니다.
function getSum(..rest: number[]) {
let sum = 0;
rest.forEach((it) => (sum += it));
return sum;
}
getSum(1, 2, 3) // 6
getSum(1, 2, 3, 4, 5) // 15
튜플 타입을 사용하여 함수에 고정된 수의 매개변수를 지정할 수 있습니다. 이 경우, 각 매개변수의 타입을 특정 순서로 지정하게 됩니다.
function getSum(...rest: [number, number, number]) {
let sum = 0;
rest.forEach((it) => (sum += it));
return sum;
}
getSum(1, 2, 3) // ✅ OK
getSum(1, 2, 3, 4) // ❌ No
함수 타입 표현식(function type expression)은 함수의 타입을 나타내는 방법 중 하나입니다. 매개변수 타입을 괄호 안에 지정하고 화살표=>
를 통해 반환 값의 타입을 지정합니다.
type Operation = (a: number, b: number) => number;
const add: Operation = (a, b) => a + b;
// const add: (a: number, b: number) => number = (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;
호출 시그니처(call signature)는 함수 타입을 정의하는 또 다른 방식입니다. 함수 타입 표현식과 마찬가지로 매개변수와 반환 값의 타입을 지정합니다.
type Operation2 = {
(a: number, b: number): number;
name: string; // hybrid type
};
const add2: Operation2 = (a, b) => a + b;
add2.name = "add";
const sub2: Operation2 = (a, b) => a - b;
const multiply2: Operation2 = (a, b) => a * b;
const divide2: Operation2 = (a, b) => a / b;
add2(1, 2); // 3
add2.name; // "add"
함수 타입의 호환성(function type compatibility)은 주어진 함수 타입이 다른 함수 타입에 대해 유효하게 사용될 수 있는지 여부를 판단하는 것을 의미합니다. TypeScript에서는 반환 값의 타입과 매개변수의 타입에 따라 함수 타입의 호환성을 결정합니다.
type A = () => number;
type B = () => 10;
let a: A = () => 10;
let b: B = () => 10;
a = b; // ✅ OK
b = a; // ❌ No
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; // ❌ No (up cast)
dogFunc = animalFunc; // ✅ OK
type Func1 = (a: number, b: number) => void;
type Func2 = (a: number) => void;
let func1: Func1 = (a, b) => {};
let func2: Func2 = (a) => {};
func1 = func2; // ✅ OK
func2 = func1; // ❌ No
함수 오버로딩(Function Overloading)은 같은 이름의 함수를 여러 개 선언하여, 주어진 매개변수의 타입과 개수에 따라 다른 동작을 수행하도록 하는 프로그래밍 기법입니다. 함수 오버로딩은 TypeScript에서 지원되지만, JavaScript에서는 지원되지 않습니다.
TypeScript에서 함수 오버로딩을 사용하려면 먼저 각 버전의 함수에 대한 오버로드 시그니처(Overload Signature)를 선언해야 합니다. 오버로드 시그니처는 함수의 이름, 매개변수의 타입과 개수, 그리고 반환 타입을 정의하지만, 함수의 구현부는 포함하지 않습니다.
그 후, 실제 함수의 동작을 정의하는 구현 시그니처(Implementation Signature)를 선언합니다. 이 구현 시그니처는 오버로드 시그니처에 나열된 모든 시그니처를 충족하는 매개변수를 가질 수 있어야 합니다.
/**
* 함수 오버로딩
*/
// 오버로드 시그니처
function func(a: number): void;
function func(a: number, b: number, c: number): void;
// 구현 시그니처
function func(a: number, b?: number, c?: number) {
if (typeof b === "number" && typeof c === "number") {
console.log(a + b + c);
} else {
console.log(a * 20);
}
}
func(1); // ✅ Ok
func(1, 2, 3); // ✅ Ok
func(1, 2); // ❌ No
사용자 정의 타입 가드(User-Defined Type Guards)는 타입스크립트에서 런타임에 특정 변수의 타입을 확인하기 위한 방법입니다. 사용자 정의 타입 가드는 프로그램의 로직을 통해 컴파일러가 직접적으로 추론할 수 없는 타입 정보를 제공하는 데 도움이 됩니다.
사용자 정의 타입 가드는 보통 함수의 형태로 정의됩니다. 이 함수는 인수의 타입을 확인하고, 그 결과를 반환합니다. 이때 반환 타입은 특별한 형태의 boolean
을 사용하여, 특정 변수가 특정 타입이라는 것을 명시적으로 나타냅니다. 이는 animal is Dog
와 같이 표현하며, 이를 타입 명제(Type Predicate)라고 합니다.
/**
* User-Defined Type Guards
*/
type Dog = {
name: string;
isBark: boolean;
};
type Cat = {
name: string;
isScratch: boolean;
};
type Animal = Dog | Cat;
// Dog 타입인지 확인하는 타입 가드
function isDog(animal: Animal): animal is Dog {
return (animal as Dog).isBark !== undefined;
}
// Cat 타입인지 확인하는 타입가드
function isCat(animal: Animal): animal is Cat {
return (animal as Cat).isScratch !== undefined;
}
function warning(animal: Animal) {
if (isDog(animal)) {
console.log(animal.isBark ? "짖습니다" : "안짖어요");
} else if(isCat(animal)) {
console.log(animal.isScratch ? "할큅니다" : "안할퀴어요");
}
}
Reference