オーバーロードの解決、this 擬似引数、そして関数の代入可能性を支配する変性の規則を理解する。
このレッスンを Kodokon で開くオーバーロードされた関数は、複数の公開シグネチャのリストと、その後に続く単一の実装シグネチャを公開します。仕様上の重要な点: 後者は外部からは見えません。呼び出せるのは宣言されたオーバーロードだけです。解決はシグネチャを上から下へたどり、最初に互換性のあるものを採用します: 最も具体的なシグネチャを必ず先頭に置きましょう。さもないと決して選ばれません。
function parse(input: string): number;
function parse(input: string[]): number[];
function parse(input: string | string[]) {
return Array.isArray(input)
? input.map((s) => s.length)
: input.length;
}
const single = parse("abc"); // number
const many = parse(["a", "bb"]); // number[]TypeScript では、先頭に this 擬似引数を宣言できます。これは出力される JavaScript から完全に消去されます: それは呼び出しコンテキストに対する純粋に静的な制約であり、noImplicitThis が有効なときにチェックされます。ThisParameterType と OmitThisParameter のユーティリティを使えばそれを抽出・削除でき、call、apply、bind とともに使われることを想定した関数を型付けするのに不可欠です。
function greet(this: { name: string }, msg: string) {
return `${msg}, ${this.name}`;
}
type Ctx = ThisParameterType<typeof greet>;
// { name: string }
type Fn = OmitThisParameter<typeof greet>;
// (msg: string) => string
const user = { name: "Ada", greet };
user.greet("Hello"); // "Hello, Ada"
// greet("Hi"); // error: missing this context変性は、型コンストラクタを通じて代入可能性がどのように伝播するかを表します。関数について、戻り値の型は共変であり、strictFunctionTypes を有効にすると、引数は反変になります: より広い型を受け付ける関数は、より狭い型を受け付ける関数の代わりになれますが、その逆は決してできません。意図的な例外が一つあります: 短縮構文で宣言されたメソッドの引数は双変のままです。これは歴史的な妥協であり、それがなければ Array<Dog> を Array<Animal> に代入できなくなります。4.7 以降、in と out で期待する変性を注釈でき(例: interface Producer<out T>)、コンパイラがそれを検証します。
interface Animal { name: string }
interface Dog extends Animal { bark(): void }
declare let f: (a: Dog) => void;
declare let g: (a: Animal) => void;
f = g; // OK: g accepts a wider type, that is safe
// g = f; // error with strictFunctionTypes
interface Sink { accept(a: Animal): void }
interface DogSink { accept(a: Dog): void }
declare let s: Sink;
declare let d: DogSink;
d = s; s = d; // both compile: bivariance!this 引数はどうなりますか?