Functions

TypeScript型システムは、関数の機能に対して多くの愛を与えています。結局の所、関数は、構成可能なシステムの核となる建築ブロックです。

パラメータの型アノテーション

もちろん、他の変数にアノテーションを付けることができるように、関数のパラメータにアノテーションを付けることもできます。

// variable annotation
var sampleVariable: { bar: number }
// function parameter annotation
function foo(sampleParameter: { bar: number }) { }

ここでは、インライン型アノテーションを使用しました。もちろん、インターフェイスなどを使用することができます

戻り値の型アノテーション

戻り値の型には、変数に使用するのと同じスタイルの関数パラメータリストの後にアノテーションを付けることができます。:Fooの例です:

interface Foo {
foo: string;
}
// Return type annotated as `: Foo`
function foo(sample: Foo): Foo {
return sample;
}

もちろん、ここではインターフェースを使用しましたが、他のアノテーション(インライン型アノテーションなど)を自由に使用できます。

コンパイラが型推論できる場合は、関数の戻り値の型アノテーションが必要ないことはよくあります。

interface Foo {
foo: string;
}
function foo(sample: Foo) {
return sample; // inferred return type 'Foo'
}

しかし、一般的には、これらのアノテーションを追加してエラー対処をしやすくする方が良い考えです。例:

function foo() {
return { fou: 'John Doe' }; // You might not find this misspelling of `foo` till it's too late
}
sendAsJSON(foo());

関数から何かを返す予定がないなら、:voidとアノテーションを付けることができます。通常、:voidを書かずに型推論に任せることができます。

オプションパラメータ

パラメータをオプションとしてマークすることができます:

function foo(bar: number, bas?: string): void {
// ..
}
foo(123);
foo(123, 'hello');

あるいは、パラメータ宣言の後に = someValueを使用してデフォルト値を提供することもできます。これは、呼び出し元がその引数を提供しない場合に設定されます。

function foo(bar: number, bas: string = 'hello') {
console.log(bar, bas);
}
foo(123); // 123, hello
foo(123, 'world'); // 123, world

オーバーロード

TypeScriptでは、関数のオーバーロードを宣言できます。これは、ドキュメントと型の安全性を高める目的に役立ちます。次のコードを考えてみましょう:

function padding(a: number, b?: number, c?: number, d?: any) {
if (b === undefined && c === undefined && d === undefined) {
b = c = d = a;
}
else if (c === undefined && d === undefined) {
c = a;
d = b;
}
return {
top: a,
right: b,
bottom: c,
left: d
};
}

コードを注意深く見ると、 abcdの意味は、渡される引数の数に応じて変化することがわかります。関数の引数は12、または4つです。これらの制約は、関数のオーバーロードを使用して強制と文書化を行うことができます。関数ヘッダを複数回宣言するだけです。最後の関数ヘッダーは、関数本体内で実際に有効なものですが、外部では使用できません。

これを以下に示します。

// Overloads
function padding(all: number);
function padding(topAndBottom: number, leftAndRight: number);
function padding(top: number, right: number, bottom: number, left: number);
// Actual implementation that is a true representation of all the cases the function body needs to handle
function padding(a: number, b?: number, c?: number, d?: number) {
if (b === undefined && c === undefined && d === undefined) {
b = c = d = a;
}
else if (c === undefined && d === undefined) {
c = a;
d = b;
}
return {
top: a,
right: b,
bottom: c,
left: d
};
}

ここで最初の3つの関数ヘッダは paddingへの有効な呼び出しとして利用できます:

padding(1); // Okay: all
padding(1,1); // Okay: topAndBottom, leftAndRight
padding(1,1,1,1); // Okay: top, right, bottom, left
padding(1,1,1); // Error: Not a part of the available overloads

もちろん、最後の宣言(関数内部から見た真の宣言)はすべてのオーバーロードと互換性があることが重要です。これは、それが関数本体が本当に必要とする関数呼び出しの性質であるからです。

TypeScriptの関数オーバーロードにランタイムでのオーバーヘッドはありません。関数が呼び出されると予想される方法を文書化し、コンパイラがコードの残りの部分をチェックするだけです。