📑 목차
타입스크립트에서는 함수를 선언할 때 매개변수 옆에 일일이 타입을 적는 방식 외에도, 함수의 타입만 따로 정의해두고 재사용하는 방법을 제공한다.
이를 가능하게 하는 두 가지 방법, 함수 타입 표현식과 호출 시그니처에 대해 알아본다.
1. 함수 타입 표현식 (Function Type Expression)
함수 타입 표현식은 타입 별칭(type)을 사용하여 함수의 타입을 별도로 정의하는 문법이다.
1-1. 기본 문법
화살표 함수와 비슷한 형태를 띤다. (매개변수 타입) => 반환값 타입 형식으로 작성한다.
// 함수 타입 정의
type Add = (a: number, b: number) => number;
// 함수 구현 (타입 별칭 사용)
const add: Add = (a, b) => a + b;
이렇게 하면 실제 함수 구현부(const add ...)에서는 매개변수의 타입을 생략해도 된다. 이미 Add 타입에서 정의했기 때문에 타입스크립트가 타입을 추론할 수 있기 때문이다.
1-2. 사용하는 이유 (재사용성)
함수 타입 표현식은 여러 함수가 동일한 타입을 가질 때 매우 유용하다.
예를 들어 계산기 기능을 만든다고 가정해 보자. 더하기, 빼기, 곱하기, 나누기 모두 (숫자, 숫자) => 숫자 형태를 가진다.
Before: 일일이 정의하는 경우
const add = (a: number, b: number) => a + b;
const sub = (a: number, b: number) => a - b;
const multiply = (a: number, b: number) => a * b;
const divide = (a: number, b: number) => a / b;
코드가 길어지고 중복이 많다.
After: 함수 타입 표현식 사용
// 공통 타입 정의
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;
코드가 훨씬 간결해졌다. 만약 나중에 타입 정의를 수정해야 한다면 Operation 타입 하나만 수정하면 되므로 유지보수성도 좋아진다.
참고: 타입 별칭 없이 인라인으로 사용할 수도 있다.
const add: (a: number, b: number) => number = (a, b) => a + b;
2. 호출 시그니처 (Call Signature)
호출 시그니처는 함수 타입 표현식과 동일한 기능을 하지만, 객체 리터럴 문법을 사용하여 정의하는 방식이다.
2-1. 기본 문법
중괄호 {}를 열고, 그 안에 (매개변수): 반환값 형태로 작성한다. (화살표 => 대신 콜론 :을 사용함에 주의하자)
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;
2-2. 왜 객체처럼 정의할까? (하이브리드 타입)
자바스크립트에서는 함수도 객체이다. 즉, 함수에 프로퍼티를 추가해서 사용할 수 있다. 호출 시그니처를 사용하면 함수이면서 동시에 일반 객체처럼 프로퍼티를 가지는 타입을 정의할 수 있다. 이를 하이브리드 타입이라고 부른다.
type Operation2 = {
(a: number, b: number): number; // 1. 함수로서 호출 가능
name: string; // 2. 일반 객체 프로퍼티 보유
};
const add2: Operation2 = (a, b) => a + b;
// 하이브리드 타입 구현을 위해 프로퍼티 추가
add2.name = "Add Function";
console.log(add2(1, 2)); // 3 (함수로 사용)
console.log(add2.name); // "Add Function" (객체로 사용)
요약
- 함수 타입 표현식:
type Name = (params) => returnType형태로, 함수의 타입을 간결하게 정의하고 재사용할 때 사용한다. - 호출 시그니처:
type Name = { (params): returnType }형태로, 객체 문법을 사용해 정의한다. - 하이브리드 타입: 호출 시그니처를 사용하면 함수 기능과 객체 프로퍼티를 동시에 가지는 타입을 정의할 수 있다.
