본문 바로가기

TypeScript

함수

함수의 타입을 결정하기 위해서는 다음 두 가지 정보가 필요하다.

  • 매개변수(parameter)의 타입
  • 반환값(return value)의 타입 (반환 타입)
    function sum(a: number, b: number): number {
      return (a + b);
    }

    function logGreetings(name: string): void {
      console.log(`Hello, ${name}!`);
    }

함수 값의 타입 표기

    const yetAnotherSum: (a: number, b: number) => number = sum;
    const onePlusOne: () => number = () => 2;
    const arrowSum: (a: number, b: number) => number = (a, b) => (a + b);

타입 별칭 또한 사용 가능하다.

type SumFunction = (a: number, b: number) => number; const definitelySum: SumFunction = (a, b) => (a + b);

기본 매개 변수

    function greetings(name: string = 'stranger'): void {
      console.log(`Hello, ${name}`);
    }
    greetings('KimJye'); // Hello, KimJye!
    greetings(); // Hello, stranger!

선택 매개 변수

많은 프로그래밍 언어는 함수 정의에 명시된 매개변수의 수보다 많거나 적은 수의 인자가 들어온 경우 에러를 뱉는다. 한편, 자바스크립트는 더 들어온 인자는 버리고, 덜 들어온 인자는 undefined가 들어온 것과 동일하게 취급한 후 어떻게든 함수를 실행하려 시도한다.


이런 언어의 특성 및 기존 사용례를 포용하면서 타입 안정성을 확보하기 위해 타입스크립트는 선택 매개변수를 지원한다. 함수의 매개변수 이름 뒤에 물음표(?) 기호를 붙여 해당 매개변수가 생략 될 수 있음을 명시할 수 있다. 예를 들어, optional?: number 로 선언된 선택 매개변수 optional를 함수 본문에서 number 타입 값으로 사용하려면 해당 값이 undefined가 아닌지를 먼저 검사해야 한다



    function fetchVideo(url: string, subtitleLanguage?: string) {
      const option = { url };
      if (subtitleLanguage) {
        option.subtitleLanguage = true;
      }
      /* ... */
    }
    fetchVideo('https://example.com', 'ko'); // okay
    fetchVideo('https://example.com'); // also okay

**이 때 매개변수 정의 순서에서 선택 매개변수 이후에 필수 매개변수를 두는 것은 허용되지 않는다**

함수 오버로딩

자바스크립트에서는 한 함수가 여러 쌍의 매개변수-반환 타입 쌍을 갖는 경우가 매우 흔하다. 이런 함수의 타입을 정의할 수 있게 하고자 타입스크립트는 함수 오버로딩(function overloading)을 지원한다.

타입스크립트의 함수 오버로딩은 다음과 같은 특징을 갖는다.

  • 함수는 하나 이상의 타입 시그니처를 가질 수 있다.
  • 함수는 단 하나의 구현을 가질 수 있다.

즉, 오버로딩을 통해서 여러 형태의 함수 타입을 정의할 수 있지만, 실제 구현은 한 번만 가능하므로 여러 경우에 대한 분기는 함수 본문 내에서 이루어져야 한다.



    function double(str: string): string;
    function double(num: number): number;
    function double(arr: boolean[]): boolean[];

    function double(arg) {
        if (typeof arg === 'string') {
            return `${arg}${arg}`;
        } else if (typeof arg === 'number') {
            return arg * 2;
        } else if (Array.isArray(arg)) {
            return arg.concat(arg);
        }
    }

    const num = double(3); // number
    const str = double('ab'); // string
    const arr = double([true, false]); // boolean[]

This 타입

함수의 this 타입을 명시하기 위해선 함수의 타입 시그니쳐에서 매개변수 가장 앞에 this 를 추가해야 한다. 이 때 this 타입은 타입 시스템을 위해서만 존재하는 일종의 가짜 타입이다. 즉, this 매개변수를 추가한다고 해도 함수가 받는 인자 수와 같은 실제 동작은 변하지 않는다.

    interface HTMLElement {
      tagName: string;
      /* ... */
    }
    interface Handler {
      (this: HTMLElement, event: Event, callback: () => void): void;
    }
    let cb: any;
    // 실제 함수 매개변수에는 this가 나타나지 않음
    const onClick: Handler = function(event, cb) {
      // this는 HTMLElement 타입
      console.log(this.tagName);
      cb();
    }

만약 this의 타입을 void로 명시한다면 함수 내부에서 this에 접근하는 일 자체를 막을 수 있다.

    interface NoThis {
      (this: void): void;
    }
    const noThis: NoThis = function() {
      console.log(this.a); // Property 'a' does not exist on type 'void'.
    }

'TypeScript' 카테고리의 다른 글

유니온 타입  (0) 2019.10.30
제네릭  (0) 2019.10.30
타입 별칭  (0) 2019.10.30
객체  (0) 2019.10.30
배열과 튜플  (0) 2019.10.30