角待ちは対空

おもむろガウェイン

Weak typeとはなにか

qiita.com

TypeScript Advent Calendar 2017の8日目の記事です。Weak typesの解説をします。

CTOにも絶賛不評だった以下の記事もおすすめです。

世界がEnumから隠した秘密をひとつひとつ見つけていこうな #TypeScript - 角待ちは対空

タイトルはよくないけど内容はよかった

2017/12/06 21:35
b.hatena.ne.jp

Excess property checksの復習

TypeScriptではオブジェクトリテラルのとき限定でExcess property checksというチェックが行われる。

つまり

interface Options {
    data?: string,
    timeout?: number,
    maxRetries?: number,
}

function sendMessage(options: Options) { }

const opts1 = {
    timeout: 10,
    payload: "hello world!", // => 余計なキー
}

sendMessage(opts1); // これは通る
sendMessage({
    timeout: 10,
    payload: "hello world!", // => 余計なキー
});
// Argument of type '{ timeout: number; payload: string; }' is not assignable to parameter of type 'Options'.
//  Object literal may only specify known properties, and 'payload' does not exist in type 'Options'.

関数の呼び出しを行う際、オブジェクトリテラルで引数を渡すときに限り、余計なプロパティが存在すると怒られていた。

あくまでオブジェクトリテラルで書くと怒られるので一旦変数に代入するか、さもなくば関数定義にインデックスシグネチャで他のプロパティをとる可能性もあることを明示すれば回避できる。

この仕様はいわゆるオプションを渡す際にありがちなバグを防ぐために導入されていた。つまりオプショナルなプロパティを渡したつもりが間違って渡していた時気づけるようになっていた。

sendMessage({
    timeout: 10,
    maxRetry:10,
});

↑の場合プロパティ名が違っている(maxRetry)のでExcess property checksに引っかかる。Excess property checksがないとmaxRetriesはオプショナルなのでスルーされてしまう。

わざわざオブジェクトリテラルで書いてあるのに余計なプロパティが存在するというのがそもそもおかしいので、Excess property checksが導入されめでたく間違ったオプションを渡す問題は解決された。

Weak type

Weak typeもオプションを引数にとるときにありがちなバグを抑止するための仕様。

具体的に見ると

interface Options {
    data?: string,
    timeout?: number,
    maxRetries?: number,
}
function sendMessage(options: Options) {}

ような関数に対して、Optionsが持つプロパティと1つも被らないオブジェクト(例えば{payload: "hello world!",retryOnFail: true})を渡せなくなった。

const opt = {
    payload: "hello world!",
    retryOnFail: true
}

sendMessage(opt)
// Type '{ payload: string; retryOnFail: boolean; }' has no properties in common with type 'Options'.

Weak typeとはOptionsのような全てのプロパティがオプショナルで指定された型を指す。Weak typeの型検査では最低1つは共通のプロパティを持たなくてはならない。(ただし空のオブジェクト{}は渡すことができる)

全てオプショナルになっていたとしてもどれか1つは存在していることを期待しているだろうという気持ちが反映された仕様。

こちらはExcess property checksと違ってオブジェクトリテラルじゃなくても(変数代入しても)効力を発揮する。

blog.yux3.net