関連

関数はfunctionから始まる書き方のものとアロー関数どちらも JavaScript のものと同じように書けます。違いは型を追加するだけです。

plusOne 関数

ある数値に1足すだけのplusOne関数を定義してみます。functionのほうで書くと以下、

function plusOne(num: number) {
  return num + 1;
}
// 暗黙的に戻り値は`number`

アロー関数で書くと以下のようになります。

const plusOne = (num: number) => {
  return num + 1;
};

引数で変数名: 型, 変数名: 型の形で定義していきます。上記のような関数は単純でだいたい何をしているか分かるので TypeScript が暗黙的に設定した戻り値の型(number)で済ますしても大丈夫そうですが、もし複雑で他人が見た時にすぐに判断できないような内容になっていると思ったら戻り値も明確にしておくといいと思います。
戻り値は(...引数): 型のように引数の括弧の後に型を書きます。上記で書いた関数にそれぞれ戻り値情報を足すと以下になります。

function plusOne(num: number): number {
  return num + 1;
}

const plusOne = (num: number): number => {
  return num + 1;
};

型を先に作りたい場合があるかもしれません。そういう場合はinterfacetypeで以下のように定義できます。

interface IPlugOne {
  (num: number): number
}

type TPlusOne1 = {
  (num: numbeer): number
}

type TPlusOne2 = (num: number) => number

これらと共にplusOneを定義するには以下のようになります。

const plugOne: IPlugOne = (num): number => num + 1

好きなプロパティを持つ関数

時々関数として実行してるのに、プロパティアクセスも行ってるものを見かけます。

foo(arg1, arg2);
console.log(foo.bar);
foo.baz = 123;

これは TypeScript でもお簡単に実装できます。関数に好きなプロパティを追加できるようになってる為です。

function foo() {}
foo.bar = 123
// またはアローで
const foo = () => {}
foo.bar = 123

上記のfooは型で表すと以下のようなインターフェースになります。

interface IFoo {
  (): void
  bar: number
}

type TFoo = {
  (): void
  bar: number
}

const foo: IFoo = () => {}
foo.bar = 123

逆に型を先に定義すると、生やせるプロパティに制約を掛けるということになります。

interface IFoo {
  (): void
  // baz に変更
  baz: number
}

const foo: IFoo = () => {}
// bar なんて知らないのでアクセスしたり値を入れれない
foo.bar = 123

ジェネリック 関数

引数がobjectのように単純ではないけれど、ある程度制約を持たせたい(fooというプロパティを持っている構造体を受け取ってその構造体を返したい)ような場合に便利です。ジェネリックは関数名のあと<T, U>のような感じで定義できるもので、これにより型定義を柔軟にすることができます。

interface A {
  value: number;
}

interface B extends A {}
interface C extends A {}

function plusOne(obj: T): T {
  obj.value = obj.value + 1;
  return obj;
};

const b: B = {value: 1};
const c: C = {value : 2}

plusOne(b); // {value: 2};
plusOne(c); // {value: 3};

extendsを使うことでTAを持っている、またはAに属していなければいけないというような制約付けができます。つまり、plusOne({foo: 1})というなものはvalueプロパティがないので型エラーになります。

また、上記では動的にTの型を設定しています。

  1. plusOne(b)bが渡ることで(obj: T)(obj: B)ということになります。

  2. (obj: B)からfunction plusOne<B>(obj: B)とジェネリクスが埋まり

  3. つまり、function plusOne<B>(obj: B): B

のように解決されます。もちろんジェネリクスは自分で設定することもできます。その場合は関数呼び出しの名前のあとにジェネリクスを設定します。

JavaScript で飯食べたい歴約 5 年、 純( nju33 ) によるノートサイトです。

このサイトではドリンク代や奨学金返済の為、広告などを貼らせて頂いてますがご了承ください。

Change Log