フロントエンド

【TypeScript関数】アロー関数やコールバック関数とオプショナル引数

TypeScriptの関数

reisuta

Webエンジニア | 20代中盤 | 大学時代はGmailすら知らないIT音痴でプログラミングとは無縁の生活を送る → 独学でプログラミングを学ぶ → Web系受託開発企業にエンジニアとして就職 → Web系自社サービス企業に転職 | 実務未経験の頃からVimを愛好しており、仕事でもプライベートでも開発はVimとTmuxを使っているので、VSCodeに疎いのが最近の悩み。何だかんだでやっぱりRubyが好き。

関数とは何か?

TypeScriptに限らず、
プログラミング言語のほとんどには、
関数という概念があります。

変数が、を使いまわしたり、名付けをしたりすることができる箱であるなら、
関数は、処理を使いまわしたり、名付けをしたりすることができる箱です。

変数について、
詳しく知りたい方は、
下記の記事をご参考ください。

TypeScript変数完全解説
参考【TypeScriptの変数】let/constと変数として使えないもの

TS Playground TS Playgroundは、TypeScriptを試すことができるサンドバッグ的環境。 通常、プログラミング言語の学習などをする際は、自分のPCに実行環境を構築する必要が ...

続きを見る

関数は、プログラムをわかりやすく分割して、
処理ごとに命名をして見通しをよくすることができます。

そのため、特に大規模のプロジェクトなどでは、
関数を使うことはもはや必須とも言えるでしょう。

実は、高校とか中学の授業とかで習う、
関数のy=2xとかも、
プログラミング言語でいう、関数のような特徴を持っています。

上記は、 xに5とかを代入したら、
10を返却する関数なので、

function linear_func(x: number): number {
  return 2 * x
}

のようにコードで表すこともできます。

つまり、何らかの値を与えて、
何らかの値を返すものが関数と考えることができるので、
概ね、高校とか中学に習った関数のイメージとは外れていません

ただ、プログラミング言語でいう、関数は、
値を返さずに処理だけを行う場合もあるという特徴はあります。
(このように値を返さない関数の返り値の型はvoidと表現します。)

TypeScriptでの関数定義方法

TypeScriptの関数宣言は、
function 関数名(引数リスト): 返り値の型 { 処理の中身 }という形の構文で 表されます。

function test(arg1: number, arg2: number): number[] {
    const val = [];
    val.push(arg1);
    val.push(arg2);
    return val
}

console.log(test(10, 30)) // [10, 30] と表示される

引数の型を間違えたり、引数の数を間違えると、
コンパイルエラーとなります。

//下記の2つはエラー
test("10", "30")
test(10)

returnによって、
関数の実行が終了して与えられた式が関数の返り値となります。

そのため、returnよりあとに書かれた部分は、
実行されません。

function test(arg1: number, arg2: number): number[] {
    const val = [];
    val.push(arg1);
    val.push(arg2);
    return val
    console.log('test') // 実行されない
}

console.log(test(10, 30)) // [10, 30] と表示される

そして、返り値にも型チェックが行われ、
test関数の返り値は、number[]でなければなりません。

返り値がない関数の宣言は、
void型を設定します。

function test(arg1: number, arg2: number): void {
    const val = [];
    val.push(arg1);
    val.push(arg2);
    console.log('test')
}

test(10, 30)

関数の定義の仕方としては、
上記の他に、変数に入れる方法もあります。

const functest = function (arg1: number, arg2: number): void {
    const val = [];
    val.push(arg1);
    val.push(arg2);
    console.log('test')
}

functest(10, 30)

変数に代入する場合は、function (引数): 返り値の型 {}というふうに定義します。
関数名は省略できます。

実際の使用ケースでは、
上記のように変数に入れる記法のほうが多い気がしますかね。

アロー関数

TypeScriptとかJavaScriptの関数定義において、
正直functionなどと書いて定義することは稀で、
ほとんどの場合こちらのアロー関数の形式で定義されているかと思われます。

構文としては、(引数): 返り値の型 => {} とします。

const functest = (arg1: number, arg2: number): void => {
    const val = [];
    val.push(arg1);
    val.push(arg2);
    console.log('test')
}

functest(10, 30)

返り値をいきなり返すような、
簡単なアロー関数であれば、更に省略することもできます。

const simplefunc = (arg1: number, arg2: number): number => arg1 + arg2
console.log(simplefunc(10, 30))

これは、(arg1: number, arg2: number): number => { return arg1 + arg2 } と同様です。

オブジェクトを返す場合は、{}と書いても、
アロー関数の中身を囲む{}とみなされてしまうので、
()で囲む必要があります。

type simpleObj = {
    val1: number
}
//正しい
const simplefunc = (arg1: number, arg2: number): simpleObj => ({ val1: arg1 + arg2 })

//エラー
const simplefunc = (arg1: number, arg2: number): simpleObj => { val1: arg1 + arg2 }

console.log(simplefunc(10, 30))

オプショナル引数

通常の関数定義の場合、
引数に定義されたものを渡さなければエラーとなりますが、
場合によっては、何も渡さずに処理したいこともあります。

その際に使用するのが、
オプショナル引数やデフォルト値の指定です。

オプショナル引数は、引数名?: 型と定義します。

const simplefunc = (arg1: number, arg2?: number): number => {
    console.log(arg1)
    console.log(arg2)
    return arg1
}

console.log(simplefunc(10))

これを実行してみるとわかるが、
オプショナル引数が省略された場合、
その引数にはundefinedが入ります。

そのため、undefinedが混入することを避けたい場合、
デフォルト値を使ったほうがいいでしょう。

デフォルト値は、引数名: 型 = 値と定義します。

const simplefunc = (arg1: number, arg2: number = 20): number => {
    console.log(arg1)
    console.log(arg2)
    return arg1 + arg2
}

console.log(simplefunc(10))

ちなみに、上記のコードをオプショナル引数として、
実行すると、arg2がundefinedになる可能性があると、
エラーになります。

デフォルト値を指定した場合、
引数にundefinedを渡すこともできるが、
その場合、デフォルト値に変換されます。

const simplefunc = (arg1: number, arg2: number = 20): number => {
    console.log(arg1)
    console.log(arg2) //20と表示される
    return arg1 + arg2
}

console.log(simplefunc(10, undefined))

コールバック関数

コールバック関数とは、関数の引数として渡される関数のことで、
これに対しコールバック関数を引数として受け取る関数を高階関数といいます。

代表的な高階関数としては、mapやfilterなどがありますね。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map

type User = { name: string, email: string }
const users: User[] = [
    { name: "Alice", email: "alice@test.com" },
    { name: "Mike", email: "mike@test.com" }
]
const callbackfunc = (user: User): string => {
    return user.name
}
const func1 = users.map(callbackfunc)
console.log(func1)//["Alice", "Mike"] と表示される

map関数に渡されている、callbackfuncがコールバック関数にあたり、
高階関数のmapは、与えられた関数を配列のすべての要素に対して呼び出して、
新しい配列を生成しています。

ジェネリクス

ジェネリクスとは、何かと考えると、
下記の記事にあるような感じの説明が適当かと思われます。

使われるまで型が決まらないようないろいろな型の値を受け入れられる機能を作るときに使います。ジェネリクスは日本語で総称型と呼ばれることもあります
https://future-architect.github.io/typescript-guide/generics.html

型引数のように、呼び出す側で型とかを指定できるような記法で、
関数の場合、<型引数>(引数): 返り値というふうに定義します。

function func1<T>(arg1: T): T[] {
    const arr: T[] = []
    arr.push(arg1)
    return arr
}

console.log(func1<number>(10)) //[10]と表示される

呼び出すときは、関数<型引数>(引数)で呼び出します。
呼び出すときに、型を指定できるので、

function func1<T>(arg1: T): T[] {
    const arr: T[] = []
    arr.push(arg1)
    return arr
}

console.log(func1<string>('arr')) //['arr']と表示される

とかもできます。

ジェネリクスについては、
下記の記事でも触れているので、
良ければご参考ください。

TypeScript/オブジェクトとジェネリクス
参考TypeScriptのオブジェクトとは何か?型の付け方とジェネリクス

オブジェクトとは何か? 下記の記事で紹介したプリミティブ型という基本的な7つの型以外のものを、オブジェクトといいます。 具体的には、string、numberbigint、boolean、undefi ...

続きを見る

  • この記事を書いた人
  • 最新記事

reisuta

Webエンジニア | 20代中盤 | 大学時代はGmailすら知らないIT音痴でプログラミングとは無縁の生活を送る → 独学でプログラミングを学ぶ → Web系受託開発企業にエンジニアとして就職 → Web系自社サービス企業に転職 | 実務未経験の頃からVimを愛好しており、仕事でもプライベートでも開発はVimとTmuxを使っているので、VSCodeに疎いのが最近の悩み。何だかんだでやっぱりRubyが好き。

おすすめ記事はこちら

Vim/Neovimプラグイン 1

プラグインをどれだけ入れるかは、その人の思想なども関係するので、一概にこれがいいというのはないかもしれません。 プラグインを全く入れない人もいれば、100個以上入れる人もいます。 ただそれでも、これだ ...

VimとNeovimの比較 2

本記事では、VimとNeovimの違いについて、解説します。 VimとNeovimの違いについては、普段頻繁にVimなどを使う方でなければ、正直、あまり気にしなくてもいいかなと思います。 ただ、Vim ...

Ruby変数やすべてがオブジェクトについて 3

本記事は、Rubyの基礎文法である、変数や真偽値、論理演算子に触れると同時に、「すべてがオブジェクト」というRubyの特徴的な思想についても解説します。 この思想は、Rubyの文法の根幹になっているの ...

4

エンジニアにおすすめの技術書 書籍学習は、エンジニアの嗜みみたいなところがありますが、 良書というものは、意外とそこまで多くもありません。 そこで本記事では「技術書マニアの筆者が厳選した技術書20選」 ...

5

エンジニアになるには? プログラミングは、専門性が高く自分一人で勉強するのが大変に感じることも多いですよね。 そこで本記事では「おすすめのプログラミングスクール5選」を特徴と、現役エンジニア目線で優れ ...

-フロントエンド