0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

型推論しない場合の関数定義について調べてみた

Posted at

型推論とは

なぜ調べようと思ったか

・何が省略できて、何が省略できないのか分からない
・各フレームワーク、ライブラリのドキュメントに記載の型指定が分からない
・ReactのFunctionコンポーネントで関数定義をするので関数の型指定の基礎を学びたい

これ以上ないくらいの型指定

アロー関数の場合
例えば以下のような関数があったとき。

//引数の型に応じて戻り値を変える関数
const arrowFunc = (param1, param2) => {
  if ((typeof param1 === "number") & (typeof param2 === "number")) {
    return param1 + param2;
  } else {
    return `${param1}${param2}`;
  }
};

この書き方が型がフル指定の型の書き方
ただ、関数定義のときと、引数と戻り値にそれぞれ指定をしていて、重複するので無駄のようです。

type funcType = {
  (param1: string | number, param2: string | number): string | number;
};

type paramType = string|number;

//引数の型に応じて戻り値を変える関数
const arrowFunc: funcType = (param1:paramType, param2:paramType) :string|number => {
  if (typeof param1 === "number" && typeof param2 === "number") {
    return param1 + param2;
  } else {
    return `${param1}${param2}`;
  }
};

なので以下いずれかで書くのが良い

type funcType = {
  (param1: string | number, param2: string | number): string | number;
};

type paramType = string|number;

//シンボルの方に型指定
const arrowFunc1: funcType = (param1, param2) => {
  if (typeof param1 === "number" && typeof param2 === "number") {
    return param1 + param2;
  } else {
    return `${param1}${param2}`;
  }
};

//関数定義の中で型指定
const arrowFunc2 = (param1:paramType, param2:paramType) :string|number => {
  if (typeof param1 === "number" && typeof param2 === "number") {
    return param1 + param2;
  } else {
    return `${param1}${param2}`;
  }
};

ジェネリック型

型定義を抽象化していくために使う。
事前に必要な型を把握しておくことは困難なので、以下のようにを使うと抽象化できる。

type funcType = {
  <T>(param1: T, param2: T): string | number;
};

//引数の型に応じて戻り値を変える関数
const arrowFunc: funcType = (param1, param2): string | number => {
  if (typeof param1 === "number" && typeof param2 === "number") {
    return param1 + param2;
  } else {
    return `${param1}${param2}`;
  }
};

上記だと、引数を持った関数が呼ばれるときに都度型が変わる。
一方、以下の形だと、関数定義をするときに型を定義もしなければならない。
こっちの手法の方がよく見かける気がする

type funcType<T> = {
  (param1: T, param2: T): string | number;
};

//引数の型に応じて戻り値を変える関数
const arrowFunc: funcType<string | number> = (param1, param2) => {
  if (typeof param1 === "number" && typeof param2 === "number") {
    return param1 + param2;
  } else {
    return `${param1}${param2}`;
  }
};
省略記法
type funcType<T> = (param1: T, param2: T)=>string | number;

//引数の型に応じて戻り値を変える関数
const arrowFunc: funcType<string | number> = (param1, param2) => {
  if (typeof param1 === "number" && typeof param2 === "number") {
    return param1 + param2;
  } else {
    return `${param1}${param2}`;
  }
};

参考記事

非常に参考になった記事。
結果的に、上記記事の内容とほぼ重複しているが、備忘録の意味も含めて投稿します。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?