레슨 4 / 8·20분
함수와 타입 가드
함수 타입 선언
TypeScript에서 함수의 매개변수와 반환 타입을 명시하면 호출 시 잘못된 인자를 컴파일 단계에서 잡을 수 있습니다. 선택적 매개변수, 기본값, 나머지 매개변수에도 타입을 지정할 수 있습니다.
typescript
// 기본 함수 타입
function add(a: number, b: number): number {
return a + b;
}
// 화살표 함수 타입
const multiply = (a: number, b: number): number => a * b;
// 선택적 매개변수와 기본값
function greet(name: string, greeting: string = "안녕"): string {
return greeting + ", " + name + "!";
}
// 나머지 매개변수
function sum(...nums: number[]): number {
return nums.reduce((a, b) => a + b, 0);
}
// 함수 타입 별칭
type Formatter = (value: number) => string;
const toWon: Formatter = (v) => v.toLocaleString() + "원";
// void와 never
function log(msg: string): void { console.log(msg); }
function throwError(msg: string): never { throw new Error(msg); }함수 오버로드
typescript
// 오버로드 시그니처
function format(value: string): string;
function format(value: number): string;
function format(value: Date): string;
function format(value: string | number | Date): string {
if (typeof value === "string") return value.trim();
if (typeof value === "number") return value.toFixed(2);
return value.toISOString();
}
format("hello"); // OK → string
format(3.14); // OK → "3.14"
format(new Date()); // OK → ISO 문자열타입 가드 (Type Guards)
타입 가드는 조건문 내에서 타입을 좁혀 (narrowing) 특정 타입의 속성에 안전하게 접근하게 합니다. typeof, instanceof, in 연산자, 그리고 사용자 정의 타입 가드를 사용합니다.
typescript
// typeof 가드
function process(value: string | number) {
if (typeof value === "string") {
return value.toUpperCase(); // string으로 좁혀짐
}
return value.toFixed(2); // number로 좁혀짐
}
// in 연산자 가드
type Fish = { swim: () => void };
type Bird = { fly: () => void };
function move(animal: Fish | Bird) {
if ("swim" in animal) {
animal.swim(); // Fish로 좁혀짐
} else {
animal.fly(); // Bird로 좁혀짐
}
}
// 사용자 정의 타입 가드 (is 키워드)
function isString(value: unknown): value is string {
return typeof value === "string";
}
function handle(input: unknown) {
if (isString(input)) {
console.log(input.toUpperCase()); // string 확정
}
}Discriminated Union
typescript
// 판별 유니온 — type 필드로 구분
type Shape =
| { kind: "circle"; radius: number }
| { kind: "rectangle"; width: number; height: number }
| { kind: "triangle"; base: number; height: number };
function area(shape: Shape): number {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "rectangle":
return shape.width * shape.height;
case "triangle":
return (shape.base * shape.height) / 2;
}
}
// exhaustiveness check — 모든 케이스를 처리했는지 확인
function assertNever(x: never): never {
throw new Error("Unexpected: " + x);
}💡
Discriminated Union + switch문은 TypeScript에서 가장 강력한 패턴 중 하나입니다. 새로운 타입을 추가하면 switch에서 처리하지 않은 케이스를 컴파일러가 알려줍니다.