関数とは何か?
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のオブジェクトとは何か?型の付け方とジェネリクス
オブジェクトとは何か? 下記の記事で紹介したプリミティブ型という基本的な7つの型以外のものを、オブジェクトといいます。 具体的には、string、numberbigint、boolean、undefi ...
続きを見る