40일차[함수 / 오버로딩 / type predicate]

진하의 메모장·2025년 3월 5일
2

공부일기

목록 보기
46/66
post-thumbnail

25 / 03 / 05

오늘 수업 시간에는 함수와 오버로딩, type predicate에 대해 배웠습니다.
자바를 배웠을 때도 오버로딩과 오버라이딩이 헷갈렸었는데, 이번에는 쉽게 정리해보겠습니다. type predicate는 이번에 처음 배우는 내용이라서 헷갈리는건지.. 뭔가가 오묘했습니다. 배운 내용대로 이해한 내용을 정리해보겠습니다.



💌 함수 선언

  • 함수의 매개변수와 반환값에 대해 타입을 명시할 수 있습니다.
function printName(name: string) {
   name;  // 매개변수 `name`의 타입이 string으로 지정됨
}

매개변수 타입 지정

  • 함수의 매개변수 타입을 : 타입 형식으로 지정합니다.

반환값 타입 지정

  • 반환값의 타입도 : 타입으로 지정할 수 있습니다.


1) 타입 체크

  • 타입스크립트는 함수에 잘못된 인수를 전달할 경우 컴파일 에러를 발생시킵니다.
function returnTwo(person1: string, person2: string): string {
   return `${person1} & ${person2}`;
}

// 잘못된 호출 예시들
returnTwo();  // 인수를 전달하지 않음 -> 에러 발생
returnTwo("이한", 1);  // 두 번째 인수가 string이 아닌 number -> 에러 발생
returnTwo("이한", "리우", "운학");  // 매개변수 개수가 맞지 않음 -> 에러 발생


2) 옵셔널 파라미터

  • 매개변수 뒤에 ?를 붙여주면 그 매개변수는 선택적입니다.
  • 값을 넣지 않아도 에러가 발생하지 않습니다.
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값이 없음)


3) 기본값 매개변수

  • 매개변수에 기본값을 설정하면, 인수가 전달되지 않으면 기본값이 사용됩니다.
function multiplyOrReturn2(x: number, y: number = 20) {
   return x * y;
}

console.log(multiplyOrReturn2(3));  // 60 (y는 기본값 20이 사용됨)


4) 나머지 매개변수

  • ...args를 사용하면 매개변수 개수에 상관없이 여러 개의 인수를 받을 수 있습니다.
  • args는 배열 형태로 전달됩니다.
function getInfinteParameter(...args: string[]) {
   return args.map((x) => `안녕 ${x}`);
}

console.log(getInfinteParameter("이한", "리우", "운학"));
// ["안녕 이한", "안녕 리우", "안녕 운학"]


5) 반환 타입 지정

  • 함수는 반환값의 타입을 지정할 수 있습니다.
  • 함수가 어떤 타입을 반환할지 미리 명시할 수 있습니다.
function add(x: number, y: number): number {
   return x + y;  // 반환값이 number 타입
}

function subtract(x: number, y: number): number {
   return x - y;  // 반환값이 number 타입
}


6) 화살표 함수

  • function 키워드 대신 =>를 사용하여 간결한 구문으로 작성할 수 있습니다.
  • 반환 타입도 지정할 수 있습니다.
const subtractArrow = (x: number, y: number): number => {
   return x - y;  // 반환값이 number 타입
};


7) 특수 반환 타입

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

  • 타입스크립트에서 오버로딩은 동일한 함수 이름을 사용하지만, 매개변수의 개수나 타입에 따라 서로 다른 동작을 하는 함수를 정의하는 방법입니다.
  • 자바스크립트에서는 함수 오버로딩을 기본적으로 지원하지 않지만, 타입스크립트에서는 오버로딩을 선언하고, 실제 구현을 별도로 처리할 수 있습니다.
  • 하나의 함수가 매개변수 개수나 타입에 따라 다르게 동작할 수 있도록 하는 방식입니다.

1) 매개변수 개수

매개변수 개수에 따른 오버로딩

  • 동일한 함수 이름인 stringOrString을 사용합니다.
  • 매개변수 개수에 따라 다른 동작을 하도록 정의합니다.
// 매개변수 1개만 받는 함수
function stringOrString(members: string): string;

// 매개변수 3개를 받는 함수
function stringOrString(
   members: string,
   members2: string,
   members3: string
): string;
  • 매개변수 개수에 따라 다른 반환값을 가진 두 개의 함수 선언을 정의할 수 있습니다.
  • 첫 번째 함수는 매개변수 하나만 받는 경우를 정의합니다.
  • 두 번째 함수는 매개변수 세 개를 받는 경우를 정의합니다.


2) 실제 함수 구현

  • 함수의 구현부는 실제 동작을 처리하는 부분입니다.
  • 매개변수의 개수에 따라 동작이 달라지도록 구현합니다.
function stringOrString(member1: string, member2?: string, member3?: string): string {
   if (member2 && member3) {
      return `모든 멤버 ${member1} & ${member2} & ${member3}`;
   } else {
      return member1;
   }
}
  • 이 함수는 세 개의 매개변수 중, 두 개 이상의 매개변수가 있을 경우 모든 멤버를 출력하고, 하나만 있을 경우 그 값만 반환합니다.
  • 옵셔널 매개변수 (member2?, member3?)를 사용하여 두 번째와 세 번째 인수는 선택적으로 받을 수 있게 설정하였습니다.


3) 함수 호출 예시

  • stringOrString("태산") → 첫 번째 인수만 전달하였으므로, "태산"만 반환됩니다.
  • stringOrString("태산", "성호", "운학") → 세 개의 인수를 전달하였으므로 "모든 멤버 태산 & 성호 & 운학"이 반환됩니다.
// "태산"
console.log(stringOrString("태산"));     

// "모든 멤버 태산 & 성호 & 운학"
console.log(stringOrString("태산", "성호", "운학")); 


4) 오류 예시

  • 오버로딩을 잘못 사용하거나 매개변수 개수를 맞추지 않으면 컴파일 에러가 발생합니다.
// 오류 발생
console.log(stringOrString("태산", "성호"));
  • stringOrString("태산", "성호")는 매개변수 두 개를 전달했는데, 두 번째 시그니처는 세 개의 인수를 요구하기 때문에 오류가 발생합니다.


💌 주요 포인트

오버로딩에 대한 주요 포인트

  • 동일한 함수 이름에 대해 다양한 시그니처를 선언하여, 매개변수의 개수나 타입에 따라 함수가 다르게 동작하도록 할 수 있습니다.
  • 오버로딩을 사용하여 시그니처에 맞는 실제 함수 구현을 작성할 때는 모든 시그니처를 커버할 수 있도록 조건을 추가합니다.
  • 각 시그니처는 매개변수의 개수와 타입에 맞게 호출되도록 설계해야합니다.


💌 Type Predicates

타입 판별 함수

  • 특정 값이 특정 타입인지를 판별하고, 해당 타입을 좁혀주는 역할을 합니다.
  • TypeScript에서 이 함수는 input is Type 형태로 반환 타입을 지정할 수 있습니다.
  • 타입을 좁히는 데 중요한 역할을 합니다.

1) 사용 예시

  • isNumber 함수는 전달된 값이 숫자인지 아닌지를 판별합니다.
  • 타입 판별 함수는 조건에 맞는 타입으로 좁혀주는 유용한 방법입니다.
  • if문 안에서 input이 실제로 어떤 타입인지 정확히 알 수 있습니다.
function isNumber(input: any): input is number {
   return typeof input === "number";
}

console.log(isNumber(1)); // true
console.log(isNumber("1")); // false
  • input is number는 타입 판별 함수를 의미합니다.
  • input이 숫자일 때만 true를 반환하고, 타입을 number로 좁혀줍니다.
  • isNumber(1)은 true를 반환하고, isNumber("1")은 false를 반환합니다.


2) 차이점

타입 판별 함수 vs 일반 함수

  • 일반적인 타입 검사 함수는 단순히 boolean 값을 반환합니다.
  • 타입 판별 함수는 타입을 좁혀주는 기능을 가지고 있습니다.
function isNumberBool(input: any): boolean {
   return typeof input === "number";
}

console.log(isNumberBool(1)); // true
console.log(isNumberBool("1")); // false
  • 이 함수는 단순히 boolean 값을 반환합니다.
  • isNumber 함수처럼 타입을 좁히지는 않습니다.
  • true를 반환하여도 input의 타입이 실제로 number인지 TypeScript가 인식하지 못합니다.


3) 타입 좁히기

  • if문 내에서 타입을 좁힐 수 있는 예시를 작성해보았습니다.
  • isNumber와 isNumberBool의 차이를 보면, 타입 판별 함수를 사용하면 조건문 안에서 변수의 타입을 안전하게 좁힐 수 있습니다.
let number: any = 5;

if (isNumberBool(number)) {
   // number가 number 타입임을 보장하지 않음
   number;
}

if (isNumber(number)) {
   // number가 number 타입으로 좁혀짐
   number;
} else {
   // number가 number가 아니면 다른 타입
   number;
}
  • isNumberBool을 사용하면 number가 number 타입인지 정확히 알지 못합니다.
  • isNumber를 사용하면 number가 실제로 number 타입인지를 확인하고, 그 후에는 number 변수의 타입이 number로 안전하게 좁혀집니다.


4) Dog와 Cat 타입 예시

  • 타입 판별 함수는 유니온 타입을 다룰 때 특히 유용합니다.
  • 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;
}
  • isNewDoge 함수는 name이 "doge"인지 확인하여 newDoge가 Doge 타입인지 판별합니다.
  • 타입을 좁혀주는 역할을 하므로, if문 안에서 newDoge는 Doge 타입으로 처리됩니다.


5) isDoge 함수 예시

  • 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일차 후기

  • 오버로딩을 사용할 때 오류가 났는지.. 모르겠어서 친구의 도움을 받았습니다.
  • 함수를 사용하는 방식은 자바스크립트와 크게 다른 부분은 없었습니다.
  • 타입을 명시해줘야하는 것을 계속 까먹는 것을 빼면 괜찮습니다.
  • 타입스크립트를 자주 사용해본 것이 아니라.. 계속 사용하면 익숙해지겠죠? ʕ๑'ㅅ'๑ʔ‧˚
profile
૮꒰ ྀི〃´꒳`〃꒱ა

0개의 댓글