[Typescript] Functions

찐새·2022년 7월 23일
0

typescript

목록 보기
3/8
post-thumbnail

3.Functions

  • typescript는 선언한 함수의 인자가 any인 것을 선호하지 않는다.
const add = (a, b) => a + b;
// Parameter 'a' implicitly has an 'any' type.
// Parameter 'b' implicitly has an 'any' type.

3-1. Call Signatures

  • 함수 타입을 명시해 인자마다 타입 적는 일을 줄일 수 있다.
type Add = (a: number, b: number) => number;

const add: Add = (a, b) => a + b;

3-2 Overloading

  • 함수가 여러 개의 Call Signatures를 가지고 있을 때 발생시킨다.
type Config = {
  path: string;
  state: object;
};

type Push = {
  (path: string): void;
  (config: Config): void;
};

const push: Push = (config) => {
  if (typeof config === "string") {
    console.log(config);
  } else {
    console.log(config.path, config.state);
  }
};
  • PushconfigConfigoverload되었다.

  • push()의 인자는 두 가지 타입을 가진다.

      1. 기본 인자 configstring이다.
      1. configstring이 아닐 때 Config 타입을 갖게 되어, config.pathconfig.state를 호출할 수 있다.
  • 타입이 같고 개수가 다른 Call Signatures를 가지고 있다면, 함수 내 나머지 인자도 타입을 지정해야 한다.

type Add = {
  (a: number, b: number): number;
  (a: number, b: number, c: number): number;
};

// Type '(a: number, b: number, c: number) => number' is not assignable to type 'Add'.
const add: Add = (a, b, c) => {
  // 'c' is declared but its value is never read.
  return a + b;
};
  • c는 옵션이기 때문에 타입을 옵셔널로 지정한다.
type Add = {
  (a: number, b: number): number;
  (a: number, b: number, c: number): number;
};

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

3-3. Polymorphism

  • 그리스어로 poly는 다수를 뜻하고, morpho-는 형태나 구조를 뜻한다. 즉, 다양한 형태라는 의미한다.
type SuperPrint = {
  (arr: number[]): void;
  (arr: boolean[]): void;
};

const superPrint: SuperPrint = (arr) => {
  arr.forEach((i) => console.log(i));
};

superPrint([1, 2, 3, 4]);
superPrint([true, false, true]);
superPrint(["a", "b", "c"]);
// Overload 2 of 2, '(arr: boolean[]): void', gave the following error.
// Type 'string' is not assignable to type 'boolean'.
superPrint([1, 2, true, false, "a"]);
// Overload 2 of 2, '(arr: boolean[]): void', gave the following error.
// Type 'string' is not assignable to type 'boolean'.
  • return하는 값이 저마다 다른 함수를 만든다면, 일일이 타입을 지정하는 것은 번거롭고 비효율적이다. 이때, polymorphism을 활용한 typescriptGeneric을 사용한다.
type SuperPrint = {
  <TypePlaceholder>(arr: TypePlaceholder[]): void;
};

const superPrint: SuperPrint = (arr) => {
  arr.forEach((i) => console.log(i));
};

superPrint([1, 2, 3, 4]);
// superPrint: <number>(arr: number[]) => void
superPrint([true, false, true]);
// const superPrint: <boolean>(arr: boolean[]) => void
superPrint(["a", "b", "c"]);
// const superPrint: <boolean>(arr: boolean[]) => void
superPrint([1, 2, true, false, "a"]);
// const superPrint: <string | number | boolean>(arr: (string | number | boolean)[]) => void
  • Generic은 단일 타입이 아닌 다양한 타입에서 작동하도록 하는, 개발자가 요구한 대로 signature를 생성해주는 도구이다.
  • Gneric이 처음 사용되는 지점을 기반으로 해당 타입을 알아낸다.
  • any처럼 하나의 타입에 얽매이지 않지만, 타입 정보를 잃지 않는다.
// any
type SuperPrint = {
  (arr: any[]): any;
};

const superPrint: SuperPrint = (arr) => arr[0];

const a = superPrint([1, 2, 3, 4]);
const b = superPrint([true, false, true]);
const c = superPrint(["a", "b", "c"]);
const d = superPrint([1, 2, true, false, "a"]);

a.toUpperCase(); // No Error

// Generic
type SuperPrint = {
  <T>(arr: T[]): T;
};

const superPrint: SuperPrint = (arr) => arr[0];

const a = superPrint([1, 2, 3, 4]);
const b = superPrint([true, false, true]);
const c = superPrint(["a", "b", "c"]);
const d = superPrint([1, 2, true, false, "a"]);

a.toUpperCase(); // Property 'toUpperCase' does not exist on type 'number'.
  • type을 선언하지 않고 만들 수 있다.
function superPrint<V>(a: V[]) {
  return a[0];
}
  • 중첩하여 Generic 사용도 가능하다.
type Player<E> = {
  name: string;
  extraInfo: E;
};

type JsExtra = {
  favFood: string;
};

type JsPlayer = Player<JsExtra>;

const js: JsPlayer = {
  name: "js",
  extraInfo: {
    favFood: "pork",
  },
};

const ts: Player<null> = {
  name: "ts",
  extraInfo: null,
};
  • 빌트인 object에도 Generic을 사용할 수 있다.
type A = Array<number>;

let a: A = [1, 2, 3, 4];

참고
Nomad coders - Typescript로 블록체인 만들기

profile
프론트엔드 개발자가 되고 싶다

0개의 댓글