chap.4 함수

유원근·2020년 12월 23일
0
post-thumbnail

타입스크립트에서의 함수

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

기존 자바스크립트에서 a,b의 합을 구하는 함수를 만들면 다음과 같이 사용할 수 있습니다.

function add(x, y) {
  return x + y;
}

타입스크립트로 바꾸며 하나씩 알아본다면,


매개변수 타입지정

타입스크립트에서는 다음과 같이 매개변수에 타입을 지정해 줄 수 있습니다.

function add(x: number, y: number) {
  return x + y;
}

반환타입 지정

타입스크립트에서 매개변수를 통해 반환되는 값을 추론해주는데, 위와같이 숫자+숫자인 경우에는 Number타입으로 반환값을 추론해 주겠죠?

물론 직접 반환 타입을 작성해 줄 수도 있습니다.

function add(x: number, y: number): number {
  return x + y;
}

함수의 반환 값이 없을때는 아래처럼 void를 지정해주어야 합니다.
function add(x:number,y:number):void{}


다음 예시를 한번 살펴볼까요?
name,email을 받아서 객체를 리턴하는 함수를 만들어보겠습니다.

function buildUserInfo(name: string, email: string) {
  return {name, email};
}

이렇게 된다면 사용할때에도 다음userdhk 같이 무조건 인자를 전달해 주어야만 하죠.

const user = buildUserInfo("conrad", "yhg0337@gmail.com");

const user2 = buildUserInfo();

하지만 두번째 user2코드처럼 값을 전달하고 싶지 않다면 어떻게 해야할까요?

인자전달

타입스크립트에서는 자바스크립트와 달리 함수에 정의된 매개변수를 모두 넘겨주어야만 합니다. (없으면 null이라도..)
하지만 위의 상황처럼 전달받을 수도 없을 수도 있는 인자가 있다면?? ?를 통해 옵션을 활용하면 됩니다.

function buildUserInfo(name?: string, email?: string) {
  return {name, email};
}

Default Parameter

이렇게 된다면 nameemail에는 undefined가 할당이 될것인데, 기본 파라미터문법을 적용해 준다면 아래와 같이 적용할 수 있습니다.

function buildUserInfo(
  name: string = "conard",
  email: string = "yhg0337@gmail.com"
) {
  return {name, email};
}

기본으로 값이 할당되기 때문에 ? 을 통해 옵션처리를 하지 않아도 괜찮겠죠?
추가적으로 기본값이 문자열이기 때문에 string이라는 타입을 지정하지 않아도 괜찮습니다.

function buildUserInfo(name = "conard", email = "yhg0337@gmail.com") {
  return {name, email};
}

Rest Parameter

es6부터 추가된 RestParameter문법은 다음과 같이 배열로 받아줄 수 있습니다.

function sum(a: number, ...nums: number[]): number {
  const totalOfNums = 0;
  for (let key in nums) {
    totalOfNums += nums[key];
  }
  return a + totalOfNums;
}

this

Vue.js에서 자주 마주하게 될 this또한 매개변수 영역에서 타입을 지정해 줄 수 있습니다.

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

화살표 함수

화살표 함수에서도 다음과 같이 일반함수와 동일한 방법으로 사용해줄수 있습니다,

const add2 = (a: number, b: number): number => a + b;

물론 위 상황에서는 반환값 추론이 가능하기 때문에 따로 지정해 줄 필요는 없겠죠?

함수의 오버로딩

자바와 같은 정적타입언어에서는 매개변수 타입과 반환타입을 지정을 해주는데, 타입스크립트도 마찬가지이죠?
자바스크립트에서는 어떤 매개변수가 들어올지도 모르며 어떤 값을 반환할지도 예상할 수 없습니다.

타입스크립트는 자바스크립트의 이런 동적인 부분들을 고정적으로 사용할 수 있게 하기 위해 오버로드 시그니처를 만들 수 있게 해줍니다

문자열의 type을 받아 Storage를 반환하는 함수의 시그니처는 다음과 같이 만들 수 있습니다.

interface Storage {}
function store(type: string): Storage

하지만 Storage를 반환하는 경우 이외에도 ColdStorage같은 값을 반활할 경우는 생길 수밖에 없습니다

“통조림”이라는 타입의 매게변수가 들어왔을 경우에는 그냥 Storage “아이스크림” 들어온 경우에는 ColdStorage를 반환하는 함수의 시그니쳐를 만들어 본다면 다음과 같습니다.

interface Storage {}
interface ColdStorage {}

function store(type: "통조림"): Storage
function store(type: "아이스크림"): ColdStorage

이렇게 문자열을 타입지정을 통해 바로 명시할 수도 있으며,
두 함수를 보면 이름과 인자, 반환값만 정의해준 것을 바로 함수 시그니쳐라고 합니다.
또한 이렇게 동일한 이름의 함수 시그니쳐를 여러개 중첩해서 작성해준것을 오버로그 시그니쳐라고 부르게 되는거에요!!

이렇게 오버로드 시그니처를 작성해주었으면, 실제 구현체를 작성해 주어야 겠죠.

먼저 StorageColdStorage를 반환해야 하기 때문에 interface에서 정의를 임시로 해줄 것입니다.

interface Storage {
  a: string;
}
interface ColdStorage {
  b: string;
}
//함수 시그니쳐
function store(type: "통조림"): Storage;
function store(type: "아이스크림"): ColdStorage;

//구현체
function store(type: "통조림" | "아이스크림") {
  if (type === "통조림") {
    return {a: "통조림"};
  } else if (type === "아이스크림") {
    return {b: "아이스크림"};
  } else {
    throw new Error("unsupported type");
  }
}

매게변수부분에서 function store(type: "통조림" | "아이스크림")이 부분은
“통조림” 혹은 “아이스크림” 타입이 들어올 수 있다는 뜻으로, 이러한 문법을 유니온타입이라고 부릅니다.

자 그렇다면 이렇게 사용할 수 있겠죠?


인자로 들어갈수 있는 두가지가 자동완성이 지원되고 있는 모습과

통조림을 넣어주면 interface에 따라 a를 사용할 수 있다고 알려주는 모습입니다.

이렇게 store라는 함수. 같은 이름의 함수 시그니처 2개를 오버로드로 작성해주고 구현체에서는 실제로 반환될 수 있는 타입을 위 코드에서 if문으로 따로 처리해 준 것처럼 각각 처리를 해주어야 합니다.

즉 오버로드 시그니처에 따라서 잘 작성해주면 되겠죠?

0개의 댓글