함수 타입

늘보·2021년 7월 10일
0

Typescript

목록 보기
2/2
  • 이 내용은 '실전 리액트 프로그래밍'(이재승 님) 책의 9장 - 정적 타입, 그리고 타입스크립트 부분을 정리한 글입니다.
  • 틀린 내용 혹은 수정이 필요한 내용이 있다면 말씀해주시면 감사하겠습니다.

함수 타입

  • 함수의 타입을 정의하기 위해서는 매개변수 타입반환 타입이 필요하다.
function getInfoText(name: string, age: number): string {
  // 매개 변수 타입과 반환 타입 지정
  const nameText = name.substr(0, 10); // 매개변수 name은 문자열 타입이기 때문에 substr 사용 가능
  const ageText = age >= 35 ? 'senior' : 'junior'; // 매개변수 age는 숫자이기 때문에 다른 숫자와 크기 비교 가능

  return `name: ${nameText}, age: ${ageText}`;
}
const v1: string = getInfoText('mike', 23);
const v2: string = getInfoText('mike', '23'); // TypeError
const v3: number = getInfoText('mike', 23); // TypeError

변수를 함수 타입으로 저장하기

  • JS에서 함수는 일급객체이므로(Javascript Deep Dive - 함수(12) 편에서 설명하였다.) 함수를 변수에 저장할 수 있다.

  • 함수를 저장할 변수의 타입은 다음과 같이 화살표 기호를 이용한다.

const getInfoText: (name: string, age: number) => void = function (name, age) {
 	// ...
};

선택 매개변수

  • 선택 매개변수는 반드시 입력하지는 않아도 되는 매개변수다.

  • 매개변수 이름 오른쪽에 물음표 기호를 입력하면 선택 매개변수가 된다.

function getInfoText(name: string, age: number, language?: string): string {
  const nameText = name.substr(0, 10);
  const ageText = age >= 35 ? 'senior' : 'junior';
  const languageText = language ? language.substr(0, 10) : '';

  return `name: ${nameText}, age: ${ageText}, language: ${languageText}`;
}
const v1: string = getInfoText('mike', 23, 'ko');
const v2: string = getInfoText('mike', 23); // language에 해당하는 인수는 반드시 입력하지는 않아도 괜찮다.
const v3: number = getInfoText('mike', 23, 123); // Type Error
function getInfoText(name: string, language?: string, age: number): void {
  // 매개변수 age에서 타입 에러 발생!
}

  • 다음은 선택 매개변수 오른쪽에 필수 매개변수가 온 경우다. 이럴 경우 컴파일 에러가 발생한다.

  • 위의 코드를 에러 없이 구현하려면 다음과 같이 undefined를 이용한다.

function getInfoText(name: string, language: string | undefined, age: number): void {
  // ...
}
  • 유니온 타입을 이용해 undefined도 입력할 수 있도록 한다.

  • 컴파일 에러가 발생하지는 않지만 가독성이 좋지 않다.

  • 매개변수의 개수가 많은 경우에는 비구조화 문법을 이용해서 명명된 매개변수로 작성하는 게 좋다.


나머지 매개변수

function getInfoText(name: string, ...rest: string[]): void {
  // ...
}
  • 나머지 매개변수는 배열로 저장할 수 있다.

this타입

  • 다음과 같이 함수의 this 타입을 정의하지 않으면 기본적으로 any 타입이 사용된다.

  • 앞에서도 말했듯 any타입은 가급적 사용하지 않는 것이 좋으므로(Any 타입을 남발하는 것을 TS를 제대로 활용하지 못하는 것이다.) this타입을 정의해 두는게 좋다.

// this타입을 정의하지 않은 코드
function getParam(this: string, index: number): string {
  const params = this.splt(',');
  if (index < 0 || params.length <= index) return '';

  return this.split(',')[index];
}
  • 일부러 splt라고 오타를 냈다. 그러나 this타입이 any가 되었기 때문에 컴파일 에러가 발생하지 않는다.
// this타입을 정의한 코드
function getParam(this: string, index: number): string {
  const params = this.splt(','); // 타입 에러 발생
  if (index < 0 || params.length <= index) return '';

  return this.split(',')[index];
}
  • 함수의 this타입은 다음과 같이 첫 번째 매개변수 위치에서 정의할 수 있다.

  • 매개변수 index는 두번째 자리에 정의되어 있따. 그러나 this 타입은 매개변수가 아니므로 index가 첫 번째 매개변수가 된다.

  • this의 타입을 정의했기 때문에 splt오타에서 타입 에러가 발생한다.


원시 타입에 메서드 추가하기

interface String {
  getParam(this: string, index: number): string; // 인터페이스를 이용해 이미 존재하는 문자열 타입에 getParam 메서드를 추가한다.
}

String.prototype.getParam = getParam; // 문자열의 프로토타입에 작성한 함수를 등록한다.
console.log('asdf, 1234, ok '.getParam(1)); // 이제 문자열에 등록된 getParam 메서드를 호출할 수 있다.

함수 오버로드: 여러개의 타입 정의하기

  • JS는 동적 타입 언어이므로 하나의 함수가 다양한 매개변수 타입과 반환 타입을 가질 수 있다.

  • 함수 오버로드(overload)를 사용하면 하나의 함수에 여러 개의 타입을 정의할 수 있다.

  • add 함수를 만들어 다음과 같은 일을 처리하고 싶다고 가정해보자.

  1. 두 매개변수가 모두 문자열이면 문자열을 반환한다.
  2. 두 매개변수가 모두 숫자이면 숫자를 반환한다.
  3. 두 매개변수를 서로 다른 타입으로 입력하면 안된다.
  • 다음은 함수 오버로드를 사용하지 않고 이 기능을 구현한 코드다.
function add(x: number | string, y: number | string): number | string {
  if (typeof x === 'number' && typeof y === 'number') return x + y;
  else {
    const result = Number(x) + Number(y);
    return result.toString();
  }
}

const v1: number = add(1, 2); // Type Error - 모든 매개변수가 숫자이면 반환값도 숫자이지만 Type Error가 발생한다.
console.log(add(1, '2')); // 두 매개변수의 타입이 달라도 Type Error가 발생하지 않는다.
  • 다음과 같이 함수 오버로드를 사용하면 이 조건을 만족하는 함수 타입을 정의할 수 있다.
// 매개변수와 반환 타입의 모든 가능한 조합을 정의한다.
function add(x: number, y: number): number;
function add(x: string, y: string): string;

// 실제 구현하는 쪽에서 정의한 타입은 함수 오버로드의 타입 목록에서 제외된다.
function add(x: number | string, y: number | string): number | string {
  if (typeof x === 'number' && typeof y === 'number') return x + y;
  else {
    const result = Number(x) + Number(y);
    return result.toString();
  }
}

const v1: number = add(1, 2);
console.log(add(1, '2')); // TypeError: 두 매개변수의 타입이 다르면 타입에러가 발생한다.

명명된 매개변수

// 우선 모든 매개변수의 이름을 정의한다.
function getInfoText({
  name,
  age = 15,
  language,
}: // 앞에 나열된 모든 매개변수에 대한 타입을 정의한다.
{
  name: string;
  age?: number;
  language?: string;
}): string {
  const nameText = name.substr(0, 10);
  const ageText = age >= 35 ? 'senior' : 'junior';

  return `name: ${nameText}, age: ${ageText}, language: ${language}`;
}
  • 명명된 매개변수의 타입을 다른 코드에서도 재사용하려면 이 다음 코드와 같이 인터페이스를 사용하면 된다.
interface Param {
  name: String;
  age?: number;
  language?: string;
}

function getInfoText({ name, age = 15, language }: Param): string {
  const nameText = name.substr(0, 10);
  const ageText = age >= 35 ? 'senior' : 'junior';

  return `name: ${nameText}, age: ${ageText}, language: ${language}`;
}

0개의 댓글