
25 / 03 / 05
오늘 수업 시간에는 함수와 오버로딩, type predicate에 대해 배웠습니다.
자바를 배웠을 때도 오버로딩과 오버라이딩이 헷갈렸었는데, 이번에는 쉽게 정리해보겠습니다. type predicate는 이번에 처음 배우는 내용이라서 헷갈리는건지.. 뭔가가 오묘했습니다. 배운 내용대로 이해한 내용을 정리해보겠습니다.
- 함수의 매개변수와 반환값에 대해 타입을 명시할 수 있습니다.
function printName(name: string) { name; // 매개변수 `name`의 타입이 string으로 지정됨 }
매개변수 타입 지정
: 타입 형식으로 지정합니다.반환값 타입 지정
: 타입으로 지정할 수 있습니다.
- 타입스크립트는 함수에 잘못된 인수를 전달할 경우 컴파일 에러를 발생시킵니다.
function returnTwo(person1: string, person2: string): string { return `${person1} & ${person2}`; } // 잘못된 호출 예시들 returnTwo(); // 인수를 전달하지 않음 -> 에러 발생 returnTwo("이한", 1); // 두 번째 인수가 string이 아닌 number -> 에러 발생 returnTwo("이한", "리우", "운학"); // 매개변수 개수가 맞지 않음 -> 에러 발생
- 매개변수 뒤에
?를 붙여주면 그 매개변수는 선택적입니다.- 값을 넣지 않아도 에러가 발생하지 않습니다.
function multiplyOrReturn(x: number, y?: number) { if (y) { return x * y; // y가 있을 때만 곱셈 수행 } else { return x; // y가 없으면 x만 반환 } } console.log(multiplyOrReturn(3, 4)); // 12 console.log(multiplyOrReturn(3)); // 3 (y값이 없음)
- 매개변수에 기본값을 설정하면, 인수가 전달되지 않으면 기본값이 사용됩니다.
function multiplyOrReturn2(x: number, y: number = 20) { return x * y; } console.log(multiplyOrReturn2(3)); // 60 (y는 기본값 20이 사용됨)
...args를 사용하면 매개변수 개수에 상관없이 여러 개의 인수를 받을 수 있습니다.args는 배열 형태로 전달됩니다.function getInfinteParameter(...args: string[]) { return args.map((x) => `안녕 ${x}`); } console.log(getInfinteParameter("이한", "리우", "운학")); // ["안녕 이한", "안녕 리우", "안녕 운학"]
- 함수는 반환값의 타입을 지정할 수 있습니다.
- 함수가 어떤 타입을 반환할지 미리 명시할 수 있습니다.
function add(x: number, y: number): number { return x + y; // 반환값이 number 타입 } function subtract(x: number, y: number): number { return x - y; // 반환값이 number 타입 }
- function 키워드 대신
=>를 사용하여 간결한 구문으로 작성할 수 있습니다.- 반환 타입도 지정할 수 있습니다.
const subtractArrow = (x: number, y: number): number => { return x - y; // 반환값이 number 타입 };
1. void
- 함수가 값을 반환하지 않을 때 사용됩니다.
- console.log( )와 같은 출력만 하는 함수
// void 예시: 반환값이 없는 함수 function doNotReturn(): void { console.log("hello"); }
2. never
- 함수가 결코 반환하지 않는 경우에 사용됩니다.
- 무한 루프나 오류를 던지는 함수에 사용됩니다.
// never 예시: 함수가 종료되지 않거나, 에러를 던지는 함수 function throwError(): never { while (true) {} // 무한 루프 } function throwError2(): never { throw Error(); // 예외를 던짐 }
Overloading
- 타입스크립트에서 오버로딩은 동일한 함수 이름을 사용하지만, 매개변수의 개수나 타입에 따라 서로 다른 동작을 하는 함수를 정의하는 방법입니다.
- 자바스크립트에서는 함수 오버로딩을 기본적으로 지원하지 않지만, 타입스크립트에서는 오버로딩을 선언하고, 실제 구현을 별도로 처리할 수 있습니다.
- 하나의 함수가 매개변수 개수나 타입에 따라 다르게 동작할 수 있도록 하는 방식입니다.
매개변수 개수에 따른 오버로딩
- 동일한 함수 이름인 stringOrString을 사용합니다.
- 매개변수 개수에 따라 다른 동작을 하도록 정의합니다.
// 매개변수 1개만 받는 함수 function stringOrString(members: string): string; // 매개변수 3개를 받는 함수 function stringOrString( members: string, members2: string, members3: string ): string;
- 함수의 구현부는 실제 동작을 처리하는 부분입니다.
- 매개변수의 개수에 따라 동작이 달라지도록 구현합니다.
function stringOrString(member1: string, member2?: string, member3?: string): string { if (member2 && member3) { return `모든 멤버 ${member1} & ${member2} & ${member3}`; } else { return member1; } }
- stringOrString("태산") → 첫 번째 인수만 전달하였으므로, "태산"만 반환됩니다.
- stringOrString("태산", "성호", "운학") → 세 개의 인수를 전달하였으므로 "모든 멤버 태산 & 성호 & 운학"이 반환됩니다.
// "태산" console.log(stringOrString("태산")); // "모든 멤버 태산 & 성호 & 운학" console.log(stringOrString("태산", "성호", "운학"));
- 오버로딩을 잘못 사용하거나 매개변수 개수를 맞추지 않으면 컴파일 에러가 발생합니다.
// 오류 발생 console.log(stringOrString("태산", "성호"));
오버로딩에 대한 주요 포인트
- 동일한 함수 이름에 대해 다양한 시그니처를 선언하여, 매개변수의 개수나 타입에 따라 함수가 다르게 동작하도록 할 수 있습니다.
- 오버로딩을 사용하여 시그니처에 맞는 실제 함수 구현을 작성할 때는 모든 시그니처를 커버할 수 있도록 조건을 추가합니다.
- 각 시그니처는 매개변수의 개수와 타입에 맞게 호출되도록 설계해야합니다.
타입 판별 함수
- 특정 값이 특정 타입인지를 판별하고, 해당 타입을 좁혀주는 역할을 합니다.
- TypeScript에서 이 함수는 input is Type 형태로 반환 타입을 지정할 수 있습니다.
- 타입을 좁히는 데 중요한 역할을 합니다.
- isNumber 함수는 전달된 값이 숫자인지 아닌지를 판별합니다.
- 타입 판별 함수는 조건에 맞는 타입으로 좁혀주는 유용한 방법입니다.
- if문 안에서 input이 실제로 어떤 타입인지 정확히 알 수 있습니다.
function isNumber(input: any): input is number { return typeof input === "number"; } console.log(isNumber(1)); // true console.log(isNumber("1")); // false
타입 판별 함수 vs 일반 함수
- 일반적인 타입 검사 함수는 단순히 boolean 값을 반환합니다.
- 타입 판별 함수는 타입을 좁혀주는 기능을 가지고 있습니다.
function isNumberBool(input: any): boolean { return typeof input === "number"; } console.log(isNumberBool(1)); // true console.log(isNumberBool("1")); // false
- if문 내에서 타입을 좁힐 수 있는 예시를 작성해보았습니다.
- isNumber와 isNumberBool의 차이를 보면, 타입 판별 함수를 사용하면 조건문 안에서 변수의 타입을 안전하게 좁힐 수 있습니다.
let number: any = 5; if (isNumberBool(number)) { // number가 number 타입임을 보장하지 않음 number; } if (isNumber(number)) { // number가 number 타입으로 좁혀짐 number; } else { // number가 number가 아니면 다른 타입 number; }
- 타입 판별 함수는 유니온 타입을 다룰 때 특히 유용합니다.
- Dog와 Cat 타입의 객체를 다룰 때, 타입을 확인하고 타입에 맞는 처리를 할 수 있습니다.
interface Doge { name: "doge"; age: number; barking: boolean; } interface Cat { name: "cat"; breed: string; purring: boolean; } type DogeOrCat = Doge | Cat; function isNewDoge(animal: DogeOrCat): animal is Doge { return animal.name === "doge"; } const newDoge: DogeOrCat = Math.random() > 0.5 ? { name: "doge", age: 3, barking: true } : { name: "cat", breed: "good", purring: false }; if (isNewDoge(newDoge)) { // newDoge는 Doge 타입으로 좁혀짐 newDoge; } else { // newDoge는 Cat 타입 newDoge; }
- isDoge 함수는 age 속성이 undefined가 아니라면 animal이 Doge임을 판별합니다.
- doge 객체가 Doge 타입으로 좁혀지고, 해당 타입에 맞는 처리를 할 수 있습니다.
function isDoge(animal: DogeOrCat): animal is Doge { return (animal as Doge).age !== undefined; } const doge: DogeOrCat = { name: "doge", age: 3, barking: true }; if (isDoge(doge)) { // doge는 Doge 타입 console.log(doge); } else { // doge는 Cat 타입 console.log(doge); }
40일차 후기
- 오버로딩을 사용할 때 오류가 났는지.. 모르겠어서 친구의 도움을 받았습니다.
- 함수를 사용하는 방식은 자바스크립트와 크게 다른 부분은 없었습니다.
- 타입을 명시해줘야하는 것을 계속 까먹는 것을 빼면 괜찮습니다.
- 타입스크립트를 자주 사용해본 것이 아니라.. 계속 사용하면 익숙해지겠죠? ʕ๑'ㅅ'๑ʔ‧˚