Post

[TypeScript] 함수 타입

[TypeScript] 함수 타입

데브타스

타입스크립트 함수 타입

함수

  • 매개 변수반환 값의 타입을 지정해주는 것
  • 함수 선언문, 함수 표현식, 화살표 함수의 방식이 존재

반환 값의 타입

  • 함수의 결과로 내보내는 return의 타입을 의미
  • 결과를 받는 변수까지 타입을 지정하는 것은 드묾
  • void

    ⇒ 아무것도 반환하지 않음

    1
    2
    3
    4
    
        function greet(): void {
          console.log("Greet!");
        }
        greet();
    
  • number

    ⇒ 숫자 값을 반환

    1
    2
    3
    4
    5
    
        function sum(n1: number, n2: number): number {
          return n1 + n2;
        }
        const res = sum(10, 20);
        console.log(res);
    

다양한 함수 형태

  • 매개 변수반환 값의 타입에 따라, 다양한 함수 형태를 지정
  • string → void

    1
    2
    3
    4
    
        function printValue(value: string): void {
          console.log(value);
        }
        printValue("A");
    
  • number[] → number

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
        function add(numbers: number[]): number {
          return numbers.reduce((res, num) => res + num, 0);
        }
        const result = add([1, 3, 5]);
        console.log(result);
          
          
        // ... 연산자 사용
          function add(...numbers: number[]): number {
          return numbers.reduce((res, num) => res + num, 0);
        }
        const result = add(1, 3, 5);
        console.log(result);
    
  • { } → void

    1
    2
    3
    4
    
        function printObj(userObj: { name: string }): void {
          console.log(userObj.name);
        }
        printObj({ name: "jaegeon" });
    

함수 표현 방식

  • 함수 선언문

    function() {…}

  • 함수 표현식

    const f1 = function() {…}

  • 함수 표현식함수 선언문과 다르게, 다음과 같은 형식을 가진다.
    1. 함수 자체매개 변수반환 값의 타입을 지정해주는 방식

      1
      2
      3
      4
      5
      
           const sum = function sum(n1: number, n2: number): number {
             return n1 + n2;
           }
           const res = sum(10, 20);
           console.log(res);
      
    2. 변수에 함수의 매개 변수반환 값의 타입을 지정해주는 방식

      1
      2
      3
      4
      5
      
           const sum: (a: number, b: number) => number = function sum(n1, n2) {
             return n1 + n2;
           }
           const res = sum(10, 20);
           console.log(res);
      
      • 해당 방식은 변수에 타입을 지정했으므로,
        굳이 함수 자체에 타입을 지정하지 않아도 됨.
      • 또한, 변수에 타입을 지정할 때 나타내는 변수명도 변경 가능.
  • 화살표 함수

    const f1 = () ⇒ {…}

    • 예시

      1
      2
      3
      4
      5
      6
      7
      
          const sum: (n1: number, n2: number) => number = (n1, n2) => n1 + n2;
          const res = sum(10, 20);
          console.log(res);
                
          // 다른 표현 방법
          const sum = (n1: number, n2: number): number => n1 + n2;
                
      



유니언 타입

| (파이프기호)

  • 유니언 타입이라 불리며, 타입을 복수개 지정이 가능함.
  • 예시

    1
    2
    3
    4
    5
    6
    
        function printValue(value: number | string): void {
          console.log(value);
        }
          
        printValue(10);  // number도 올 수 있고
        printValue("a"); // string도 올 수 있음!
    

→ 주의사항: 유니언 타입을 중첩해서 사용할 때, 괄호로 묶는 범위를 유의한다!

Type Guard: 타입을 좁혀주는 행위

  • 특정 타입에 따라, 결과물을 출력하거나 반환하고 싶으면,
    typeof조건문을 활용하여 타입을 좁혀줌.

    1
    2
    3
    4
    5
    6
    7
    
      function printValue(value: number | string): void {
          if (typeof value === "number") console.log(value.toFixed(0));
          else console.log(value);
        }
          
      printValue(10.123); // number일 때, 소수점 자릿수 숫자 없애기
      printValue("a");    // 그 외의 경우, 그대로 출력
    
  • 반환 값의 타입에도 중복 지정 가능 → 타입 좁혀주기도 가능.

    1
    2
    3
    4
    5
    6
    
      const sum = (n1: number | string, n2: number | string): number | string => {
          if (typeof n1 === "number" && typeof n2 === "number") return n1 + n2;
          else return `${n1}${n2}`;
        };
      console.log(sum(10, 20));   // 둘 다 number 이므로 더해줌
      console.log(sum("A", "B")); // 그 외의 경우는 연결 연산
    

→ 주의사항: 타입을 좁혀줄 때, 예외인 타입이 없게 조건문을 작성한다.

→ 주의사항: 타입이 정해져 있어도,
해당 타입의 값이 안 넘어올 수 있는 경우도 고려해야 한다!



void vs never

void

  • 아무 값도 반환하지 않음 → 함수에서 반환 값이 없음!

never

  • 절대 반환하지 않음 → 무한 반복 or 에러 발생 시에 사용!

    1
    2
    3
    4
    5
    6
    7
    8
    
        let obj: Record<string, never> = {};
        function throwError(message: string): never {
          throw new Error(message);  // 에러 발생
        }
        
        function infinitLoop(): never {
          while (true) {} // 무한 반복
        }
    

→ 의미상 비슷하여, 혼용하여 사용할 수 있으나, 구분할 줄 알아야 함!



함수 오버로드

  • 함수가 복수 개의 타입의 인자에 대해 다른 동작을 할 수 있게 함.
  • 구현문 이외에, 오버로드를 정의하고 → 타입에 따라 여러개 정의 가능!
  • 함수 선언문에서만 사용할 수 있음! (함수 표현식, 화살표 함수 사용 X)
  • 예: number로 반환되는 값에 대해, 다음과 같이 수행

    [기존에는 수행 X]

    1
    2
    3
    4
    5
    6
    7
    
      function sum(n1: number | string, n2: number | string): number | string {
          if (typeof n1 === "number" && typeof n2 === "number") return n1 + n2;
          else return `${n1}${n2}`;
      }
      const res1 = sum(1.2, 2.3);
      console.log(res1); // 3.5
      console.log(res1.toFixed(0));   // error 발생
    

    [오버로드를 사용하면, 정상 수행]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
      function sum(n1: number, n2: number): number;
      function sum(n1: string, n2: number): string;
      function sum(n1: number, n2: string): string;
      function sum(n1: string, n2: string): string;
      function sum(n1: number | string, n2: number | string): number | string {
          if (typeof n1 === "number" && typeof n2 === "number") return n1 + n2;
          else return `${n1}${n2}`;
      }
      const res1 = sum(1.2, 2.3);
      console.log(res1); // 3.5
      console.log(res1.toFixed(0));   // 정상적으로 동작 (결과: 4)
    

→ 주의사항: 역시, 예외인 타입이 없게 작성한다.



타입 단언

  • 함수 오버로드 방식 이외에, 다음 방법을 사용할 수 있음
  • 나온 결과 값에 as를 사용하여 타입을 단언할 수 있음

    1
    2
    3
    4
    5
    6
    7
    
      function sum(n1: number | string, n2: number | string): number | string {
          if (typeof n1 === "number" && typeof n2 === "number") return n1 + n2;
          else return `${n1}${n2}`;
      }
      const res1 = sum(1.2, 2.3) as string;
      console.log(res1); 
      console.log(res1.toFixed(0));   
    



옵셔널 파라미터 ?

  • 옵셔널 파라미터 ?를 붙이면, 옵셔널 속성이 된다.
  • 옵셔널 속성: 해당 속성에 해당하는 값이 와도 되고, 안와도 된다.

    1
    2
    3
    4
    5
    6
    7
    
        function printUserInfo(name: string, age?: number): void {
          if (name && age) console.log(`${name}, ${age}`);
          else console.log(`${name}`);
        }
        
        printUserInfo("jaegeon", 26);
        printUserInfo("jeongsue"); // age가 안와도 정상동작
    

→ 주의사항: 앞에 오는 파라미터에 단독으로 옵셔널 파라미터를 붙일 수 없다!


This post is licensed under CC BY 4.0 by the author.