[TypeScript] 함수

Jeris·2023년 6월 8일
0

TypeScript

목록 보기
4/11
post-custom-banner

함수 타입

함수의 매개변수와 반환 값의 타입을 지정할 수 있습니다.

function func(a: number, b: number) {
  return a + b; // func(): number (type assertion)
}

/**
* arrow function type definition
*/

const add = (a: number, b: number) => a + b; // add(): number (type assertion)

선택적 매개변수와 기본 매개변수

함수에 선택적 매개변수를 제공할 수도 있습니다. 이를 위해서는 매개변수 뒤에 '?'를 추가하면 됩니다. 또한 매개변수에 기본값을 설정할 수도 있습니다. 이 경우, 매개변수에 값이 제공되지 않을 경우에 사용될 값을 지정하면 됩니다. 선택적 매개변수는 항상 맨 뒤에 위치해야합니다.

function introduce(name = "이정환", age: number, tall?: number) {
  console.log(`name: ${name}`);
  if (typeof tall === "number"){
    console.log(`tall: ${tall + 10}`);
  }
}

나머지 매개변수

함수에 임의의 수의 매개변수를 전달할 수 있도록 하려면 나머지 매개변수(Rset Parameter)를 사용할 수 있습니다. 이를 위해서는 매개변수 이름 앞에 '...'를 추가하면 됩니다.

function getSum(..rest: number[]) {
  let sum = 0;
  rest.forEach((it) => (sum += it));
  
  return sum;
}

getSum(1, 2, 3) // 6
getSum(1, 2, 3, 4, 5) // 15

튜플 타입 매개변수

튜플 타입을 사용하여 함수에 고정된 수의 매개변수를 지정할 수 있습니다. 이 경우, 각 매개변수의 타입을 특정 순서로 지정하게 됩니다.

function getSum(...rest: [number, number, number]) {
  let sum = 0;
  rest.forEach((it) => (sum += it));
  return sum;
}

getSum(1, 2, 3) // ✅ OK
getSum(1, 2, 3, 4) // ❌ No

함수 타입 표현식

함수 타입 표현식(function type expression)은 함수의 타입을 나타내는 방법 중 하나입니다. 매개변수 타입을 괄호 안에 지정하고 화살표=>를 통해 반환 값의 타입을 지정합니다.

type Operation = (a: number, b: number) => number;

const add: Operation = (a, b) => a + b;
// const add: (a: number, b: number) => number = (a, b) => a + b;
const sub: Operation = (a, b) => a - b;
const multiply: Operation = (a, b) => a * b;
const divide: Operation = (a, b) => a / b;

호출 시그니처

호출 시그니처(call signature)는 함수 타입을 정의하는 또 다른 방식입니다. 함수 타입 표현식과 마찬가지로 매개변수와 반환 값의 타입을 지정합니다.

type Operation2 = {
  (a: number, b: number): number;
  name: string; // hybrid type
};

const add2: Operation2 = (a, b) => a + b;
add2.name = "add";
const sub2: Operation2 = (a, b) => a - b;
const multiply2: Operation2 = (a, b) => a * b;
const divide2: Operation2 = (a, b) => a / b;

add2(1, 2); // 3
add2.name; // "add"

함수 타입의 호환성

함수 타입의 호환성(function type compatibility)은 주어진 함수 타입이 다른 함수 타입에 대해 유효하게 사용될 수 있는지 여부를 판단하는 것을 의미합니다. TypeScript에서는 반환 값의 타입과 매개변수의 타입에 따라 함수 타입의 호환성을 결정합니다.

반환 값의 타입 호환성

type A = () => number;
type B = () => 10;

let a: A = () => 10;
let b: B = () => 10;

a = b; // ✅ OK
b = a; // ❌ No

매개변수의 타입 호환성

type Animal = {
  name: string;
};

type Dog = {
  name: string;
  color: string;
};

let animalFunc = (animal: Animal) => {
  console.log(animal.name);
};

let dogFunc = (dog: Dog) => {
  console.log(dog.name);
  console.log(dog.color);
};

animalFunc = dogFunc; // ❌ No (up cast)
dogFunc = animalFunc; // ✅ OK

매개변수의 수와 호환성

type Func1 = (a: number, b: number) => void;
type Func2 = (a: number) => void;

let func1: Func1 = (a, b) => {};
let func2: Func2 = (a) => {};

func1 = func2; // ✅ OK
func2 = func1; // ❌ No

함수 오버로딩

함수 오버로딩(Function Overloading)은 같은 이름의 함수를 여러 개 선언하여, 주어진 매개변수의 타입과 개수에 따라 다른 동작을 수행하도록 하는 프로그래밍 기법입니다. 함수 오버로딩은 TypeScript에서 지원되지만, JavaScript에서는 지원되지 않습니다.

TypeScript에서 함수 오버로딩을 사용하려면 먼저 각 버전의 함수에 대한 오버로드 시그니처(Overload Signature)를 선언해야 합니다. 오버로드 시그니처는 함수의 이름, 매개변수의 타입과 개수, 그리고 반환 타입을 정의하지만, 함수의 구현부는 포함하지 않습니다.

그 후, 실제 함수의 동작을 정의하는 구현 시그니처(Implementation Signature)를 선언합니다. 이 구현 시그니처는 오버로드 시그니처에 나열된 모든 시그니처를 충족하는 매개변수를 가질 수 있어야 합니다.

/**
* 함수 오버로딩
*/

// 오버로드 시그니처
function func(a: number): void;
function func(a: number, b: number, c: number): void;

// 구현 시그니처
function func(a: number, b?: number, c?: number) {
  if (typeof b === "number" && typeof c === "number") {
    console.log(a + b + c);
  } else {
    console.log(a * 20);
  }
}

func(1);        // ✅ Ok
func(1, 2, 3);  // ✅ Ok
func(1, 2);     // ❌ No

사용자 정의 타입 가드

사용자 정의 타입 가드(User-Defined Type Guards)는 타입스크립트에서 런타임에 특정 변수의 타입을 확인하기 위한 방법입니다. 사용자 정의 타입 가드는 프로그램의 로직을 통해 컴파일러가 직접적으로 추론할 수 없는 타입 정보를 제공하는 데 도움이 됩니다.

사용자 정의 타입 가드는 보통 함수의 형태로 정의됩니다. 이 함수는 인수의 타입을 확인하고, 그 결과를 반환합니다. 이때 반환 타입은 특별한 형태의 boolean을 사용하여, 특정 변수가 특정 타입이라는 것을 명시적으로 나타냅니다. 이는 animal is Dog와 같이 표현하며, 이를 타입 명제(Type Predicate)라고 합니다.

/**
* User-Defined Type Guards
*/

type Dog = {
  name: string;
  isBark: boolean;
};

type Cat = {
  name: string;
  isScratch: boolean;
};

type Animal = Dog | Cat;

// Dog 타입인지 확인하는 타입 가드
function isDog(animal: Animal): animal is Dog {
  return (animal as Dog).isBark !== undefined;
}

// Cat 타입인지 확인하는 타입가드
function isCat(animal: Animal): animal is Cat {
  return (animal as Cat).isScratch !== undefined;
}

function warning(animal: Animal) {
  if (isDog(animal)) {
    console.log(animal.isBark ? "짖습니다" : "안짖어요");
  } else if(isCat(animal)) {
    console.log(animal.isScratch ? "할큅니다" : "안할퀴어요");
  }
}

Reference

profile
job's done
post-custom-banner

0개의 댓글