【読書メモ】初めてのTypeScript - 第II部 TypeScript の機能
5章 関数
関数のパラメーター
変数と同様に、TypeScript
では、型アノテーションを使って関数パラメーターの型を宣言できます。
function attack(damage: number) {
console.log(`${damage} のダメージを与えた`)
}
型アノテーションの中で :
の前に ?
を追加することで、パラメーターをオプションと指定できます。オプションパラメーターは、必ず 最後 のパラメーターでなければなりません。
function announceAttack(damage: number, target?: string) {
if (target) {
console.log(`${target} に ${damage} のダメージを与えた`)
} else {
console.log(`${damage} のダメージを与えた`)
}
}
announceAttack(10)
announceAttack(10, 'ピカチュウ')
announceAttack(10, undefined)
function announceAttack(target?: string, damage: number) {
// Error: A required parameter cannot follow an optional parameter.
}
TypeScript
の型推論は、デフォルト値を持つ関数パラメーターに対して、初期値を持つ変数の場合と同様に機能します。
function announceAttack(damage: number, target = 'ピカチュウ') {
console.log(`${target} に ${damage} のダメージを与えた`)
}
announceAttack(10)
announceAttack(10, 'ゼニガメ')
announceAttack(10, undefined)
レストパラメーター の型は、配列の型として指定します。
function announceAttacks(damage: number, ...targets: string[]) {
targets.forEach((target) => {
console.log(`${target} に ${damage} のダメージを与えた`)
})
}
announceAttacks(10, 'ピカチュウ', 'ゼニガメ', 'フシギダネ')
戻り値の型
TypeScript
は洞察力の鋭い言語であり、関数の戻り値の型を推論できます。異なる値を返す複数の return
文が関数に含まれる場合、TypeScript
は戻り値の型を、関数が返し得る全ての型の合併型と推論します。
function getAttackMessage(damage: number) {
if (damage >= 20) {
return '効果は抜群だ!'
} else if (damage >= 10) {
return '効果は普通だ'
} else if (damage >= 5) {
return '効果はいまひとつだ'
} else {
return undefined
}
}
関数の戻り値の型を明示的に宣言することもできます。
function getAttackMessage(damage: number): string | undefined {
if (damage >= 20) {
return '効果は抜群だ!'
} else if (damage >= 10) {
return '効果は普通だ'
} else if (damage >= 5) {
return '効果はいまひとつだ'
} else {
return undefined
}
}
const getAttackMessageArrow = (damage: number): string | undefined => {
if (damage >= 20) {
return '効果は抜群だ!'
} else if (damage >= 10) {
return '効果は普通だ'
} else if (damage >= 5) {
return '効果はいまひとつだ'
} else {
return undefined
}
}
関数の型
JavaScript
では、関数を値として渡すことができますので、関数の型を宣言することができます。
let attackFunction: (damage: number, target?: string) => string
type AttackFunction = (damage: number, target?: string) => string
void
void
型は、関数が何も返さないことを示します。関数の型の宣言で使われる場合、void
その関数から返された値が全て無視されることを表します。
function logAttack(damage: number): void {
console.log(`${damage} のダメージを与えた`)
}
never
関数の中には、値を返さないだけでなく、呼び出し元に全く処理を返さないものさえあります。常にエラーをスローしたり、無限ループを実行したりする関数がこれに当たります。
処理を返さない関数に対しては、never
という型アノテーションを明示的に追加することで、その関数の呼び出し後のコードが一切実行されないことを表現できます。
function fail(message: string): never {
throw new Error(message)
}
function workWithUnsafeParam(param: unknown) {
if (typeof param !== 'string') {
return fail('パラメーターは文字列である必要があります')
}
console.log(param.toUpperCase())
}
関数のオーバーロード
JavaScript
の関数の中には、オプションパラメーターやレストパラメーターだけでは表現できない、大幅に異なるパラメーターのセットを使って呼び出せるものもあります。このような関数は、オーバーロードシグネチャ と呼ばれる TypeScript
の構文を使って表せます。
function announceAttack(damage: number, target: string): void
function announceAttack(damage: number, targets: string[]): void
function announceAttack(
damage: number,
targetOrTargets: string | string[],
): void {
if (Array.isArray(targetOrTargets)) {
targetOrTargets.forEach((target) => {
console.log(`${target} に ${damage} のダメージを与えた`)
})
} else {
console.log(`${targetOrTargets} に ${damage} のダメージを与えた`)
}
}