Programming Language/TypeScript

[TypeScript] Call Signature 와 Index Signature

영벨롭 2023. 12. 26. 19:06

📌 호출 시그니쳐(Call Signature)

 Call Signature란 함수의 매개변수와 반환 값의 타입을 type 또는 interface 로 미리 선언하는 것입니다. 

 즉, 함수의 구현이 아닌, 함수의 타입을 정의하는 것입니다. 

 

일반적인 함수 선언 방법은 다음과 같습니다. 

function add(a: number, b: number): number {
  return a + b;
}
const sub = (a: number, b: number): number => {
  return a - b;
};

 

이를 호출 시그니쳐를 이용하여 표현하면 다음과 같습니다. 

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

const add: Operation = (a, b) => a + b;
const sub: Operation = (a, b) => a - b;

console.log(add(1, 2));
console.log(sub(1, 2));
interface Operation {
  (a: number, b: number): number;
}

const add: Operation = (a, b) => a + b;
const sub: Operation = (a, b) => a - b;

console.log(add(1, 2));
console.log(sub(1, 2));

 

✅ 오버로딩 (Overloading)

 함수 오버로딩은 함수 이름은 동일하고 매개 변수만 다른 여러 개의 함수를 정의하는 것을 말합니다. 

 

 매개 변수의 타입이 다른 경우에 마지막 줄은 에러를 발생시킵니다. 

 a 타입은 (number | string) 인데, number 와 string 은 더할 수가 없어서 에러가 발생됩니다. 

interface Add {
  (a: number, b: number): number;
  (a: string, b: number): number;
}

const add: Add = (a, b) => a + b; // Error!
// '+' 연산자를 'string | number' 및 'number' 형식에 적용할 수 없습니다.

 

 이때 변수의 타입 별로 처리를 해야합니다. a 타입이 number 일 때는 a + b 를, a 타입이 string 일 때는 b 를 리턴합니다.  

const add: Add = (a, b) => {
  if (typeof a === "number") {
    return a + b;
  } else return b;
};

 

 매개 변수의 개수가 다른 경우, optional 변수로 설정합니다. 이때 optional 변수로 설정한 변수에는 타입을 꼭 지정해 주어야 합니다. 

interface Add {
  (a: number, b: number): number;
  (a: string, b: number): number;
  (a: number, b: number, c: number): number;
}
const add: Add = (a, b, c?: number) => {
  if (typeof a === "number") {
    if (c) return a + b + c;
    else return a + b;
  } else return b;
};

📌 인덱스 시그니쳐(Index Signature)

 Index Signature { [Key: Type]: valueType } 형식으로 구성되며, type 또는 interface 키워드로 정의할 수 있습니다.

 객체가 여러 Key 를 가질 수 있으며, Key 와 매핑되는 Value 를 가지는 경우 사용됩니다. 

 주의해야할 점은, Key 타입으로 string, number, symbol, Template literal 만 가능합니다. 

type Type1 = {
  [key: string]: unknown;
};
interface Type2 {
  [key: number]: string;
}

let obj: Type1 = {
  name: "John",
  age: 20,
};
obj["description"] = "Hello world";
console.log(obj); // { name: 'John', age: 20, description: 'Hello world' }

 

 또한 다음과 같이 객체 내부에 존재하는 속성의 값을 모두 합산해야하는 경우, 인덱스 시그니쳐를 사용하여 함수의 매개변수 타입으로 지정합니다. 

let fees = {
  taxi: 4800,
  subway: 1400,
  bus: 1250,
};

function addFees(fees: { [key: string]: number }) {
  let ret: number = 0;
  for (let key in fees) {
    ret += fees[key];
  }
  return ret;
}

 

 인덱스 시그니쳐의 Key 타입이 number 일 경우, 배열처럼 사용이 가능합니다. 

interface Type {
  [key: number]: string;
}
let tmp1: Type = {};
let tmp2: Type = [];

tmp1[0] = "Hello"; // { 0: "Hello" }
tmp2[0] = "World"; // ["World"]

let tmp3: Type = ["Hello", "World"];

 

 Key 타입이 여러 개인 경우 다음과 같이 사용합니다. 

interface Type {
  [index: number]: string;
  [key: string]: string;
}

let temp: Type = {
  0: "Hello",
  description: "World",
};
console.log(temp); // { 0: "Hello", description: "World" }

 

✅ Index Signature 를 사용하는 경우

  • 객체의 특정 value 에 접근하고 싶을 때
  • 객체의 속성들(key, value)의 모든 이름이나 type을 명확히 알지 못할 때, 속성의 type만 우선 지정해주어 객체의 정보들에 접근하기 위해 사용
  • 속성의 type 만 알고있는 경우
반응형