Typescript 개념잡기(2)

오형근·2022년 5월 5일
0

Typescript

목록 보기
2/15
post-thumbnail

이어서 타입스크립트의 함수에 대한 이야기를 해보자.

타입스크립트 핸드북(타입스크립트 핸드북)을 보고 공부한 것을 정리한 글입니다.
기본적인 JS 지식은 가진 상태라고 가정합니다.


## 타입스크립트에서의 함수

웹 애플리케이션을 구현할 때 자주 사용되는 함수는 타입스크립트로 크게 다음 3가지 타입을 정의할 수 있다.

  • 함수의 파라미터(매개변수) 타입
  • 함수의 반환 타입
  • 함수의 구조 타입

즉 함수의 파라미터, 반환값, 구조에 대해서 각각 별도의 타입을 지정해줄 수 있다는 말이다.

함수의 기본적인 타입 선언

다음 자바스크립트 함수를 보자.

function sum(a, b) {
  return a + b;
}

위의 함수에 타입을 부여하면 다음과 같다.

function sum(a: number, b: number): number {
  return a + b;
}

기존 자바스크립트 함수 선언 방식에서 매개변수와 함수의 반환 값에 타입을 추가하였다.

만일 함수가 아무 반환값이 없다고 하면 void를 사용하도록 하자.

함수의 인자

타입스크립트에서는 함수의 인자를 모두 필수 값으로 간주한다. 따라서 함수의 매개변수를 설정하면 undefinednull값이라도 무조건 넘겨야 하며, JS로 컴파일하는 과정에서 정의된 매개변수 값이 넘어왔는지 확인한다.

다시 말해 정의된 매개변수 값만 받을 수 있고 추가로 인자를 받을 수 없다는 의미이다.

다음 코드를 살펴보자.

function sum(a: number, b: number): number {
  return a + b;
}
sum(10, 20); // 30
sum(10, 20, 30); // error, too many parameters
sum(10); // error, too few parameters

위와 같은 특성은 정의된 매개변수의 갯수 만큼의 인자를 넘기지 않아도 되는 자바스크립트의 특성과 반대된다. 만일 이런 특성을 살리고 싶다면 ?를 이용해 다음과 같이 정의할 수 있다.

function sum(a: number, b?: number): number {
  return a + b;
}
sum(10, 20); // 30
sum(10, 20, 30); // error, too many parameters
sum(10); // 10

ES6 문법과 같은 방식으로 매개변수 초기화를 진행할 수 있다.

function sum(a: number, b = '100'): number {
  return a + b;
}
sum(10, undefined); // 110
sum(10, 20, 30); // error, too many parameters
sum(10); // 110

rest가 적용된 매개변수

rest 메소드를 이용해 다음과 같이 함수를 작성할 수 있다.

function sum(a: number, ...nums: number[]): number {
  const totalOfNums = 0;
  for (let key in nums) {
    totalOfNums += nums[key];
  }
  return a + totalOfNums;
}
//기존 숫자 a와 다른 숫자로 된 배열을 대입하면 해달 배열에 있는 숫자들을 모두 a에 더한 값을 반환.

this

타입스크리비트에서 자바스크립트의 this가 잘못 사용되었을 때 감지할 수 있다.
타입스크립트에서 this의 타입을 명시하려면 다음과 같은 방법을 사용한다.

function 함수명(this: 타입) {
  // ...
}

이를 실제로 적용한 코드는 아래와 같다.

interface Vue {
  el: string;
  count: number;
  init(this: Vue): () => {};
} 
// interface는 타입이나 객체의 형태를 정의해주는 친구라고 우선 알아만 두자.
// 뒤에서 다루게 된다.

let vm: Vue = {
  el: '#app',
  count: 10,
  init: function(this: Vue) {
    return () => {
      return this.count;
    }
  }
}

let getCount = vm.init();
let count = getCount();
console.log(count); // 10

콜백에서의 this

앞에서 살펴본 일반적인 상황에서의 this와는 다르게 콜백으로 함수가 전달되었을 때의 this를 구분해줘야 할 때가 있다. 그럴 때는 아래와 같이 강제할 수 있는데, 코드를 살펴보자.

interface UIElement {
  // 아래 함수의 `this: void` 코드는 함수에 `this` 타입을 선언할 필요가 없다는 의미입니다.
  addClickListener(onclick: (this: void, e: Event) => void): void;
}

class Handler {
    info: string;
    onClick(this: Handler, e: Event) {
        // 위의 `UIElement` 인터페이스의 스펙에 `this`가 필요없다고 했지만 사용했기 때문에 에러가 발생합니다.
        this.info = e.message;
    }
}
let handler = new Handler();
uiElement.addClickListener(handler.onClick); // error!

this는 위의 코드에서는 이벤트리스너의 타겟이 되어야 하기 때문에 thisHandler를 가리키지 못하도록 void로 지정하는 것이다. 위의 코드에서 this:void를 통해 onClick함수 내에 this를 지정하지 않아도 된다고 했으나 지정했기에 에러가 발생한다.

만일 UIElement인터페이스의 스펙에 맞춰 Handler를 구현하려면 다음과 같이 변경해야한다.

class Handler {
    info: string;
    onClick(this: void, e: Event) {
        // `this`의 타입이 void이기 때문에 여기서 `this`를 사용할 수 없습니다.
        console.log('clicked!');
    }
}
let handler = new Handler();
uiElement.addClickListener(handler.onClick);

Tip
변수에 화살표 함수를 연결하면 매번 함수가 생성되지만, 클래스의 메소드로 선언하면 모든 핸들러에 기본으로 공유되므로 한번만 생성된다!


다음에는 인터페이스에 대한 이야기를 해보자.

profile
https://nohv.site

0개의 댓글