定数に対してFlowの型を設定する場合、工夫というか、トリッキーな書き方をしないと上手く動かない。
業務で必要になり調べ、GitHubのIssueで解決策を見つけたのだが、日本語の資料や記事は見当たらなかった。
ちょっとした小ネタだが、誰かの役に立つかもしれないし、自分の備忘録も兼ねて書いておく。
Flowのバージョンは0.46.0
で、動作確認をしている。
まず、何も考えず普通に書いてみる。
// @flow const NORMAL_MEMBER_CODE = 'qwerty'; const ADMIN_CODE = 'admin'; type Code = NORMAL_MEMBER_CODE | ADMIN_CODE; function sendCode(code: Code): void { // 何らかの処理 console.log(code); } sendCode('admin');
最初に、NORMAL_MEMBER_CODE
とADMIN_CODE
という2つの定数を定義している。
sendCode
の引数は必ずCode
という型であり、これは、NORMAL_MEMBER_CODE
かADMIN_CODE
のいずれかである。
何もおかしなところはない。
しかしこれをFlowでチェックすると、エラーになる。
6: type Code = NORMAL_MEMBER_CODE | ADMIN_CODE; ^^^^^^^^^^^^^^^^^^ string. Ineligible value used in/as type annotation (did you forget 'typeof'?) 6: type Code = NORMAL_MEMBER_CODE | ADMIN_CODE; ^^^^^^^^^^^^^^^^^^ NORMAL_MEMBER_CODE 6: type Code = NORMAL_MEMBER_CODE | ADMIN_CODE; ^^^^^^^^^^ string. Ineligible value used in/as type annotation (did you forget 'typeof'?) 6: type Code = NORMAL_MEMBER_CODE | ADMIN_CODE; ^^^^^^^^^^ ADMIN_CODE
(did you forget 'typeof'?)
と出ているので、Code
の定義を以下のように書き換えてみる。
type Code = typeof NORMAL_MEMBER_CODE | typeof ADMIN_CODE;
これなら確かに、エラーは出ないようになる。
しかしこれは、Code
はstring
ですと定義しているだけであり、文字列なら何でも通ってしまう。
例えばsendCode('hoge');
でも、Flowはエラーを出さない。
qwerty
とadmin
以外ではエラーを出すのが、意図する挙動である。
正解は、以下。
// @flow const NORMAL_MEMBER_CODE: 'qwerty' = 'qwerty'; const ADMIN_CODE: 'admin' = 'admin'; type Code = typeof NORMAL_MEMBER_CODE | typeof ADMIN_CODE; function sendCode(code: Code): void { // 何らかの処理 console.log(code); } // sendCode('hoge'); // Found 1 error sendCode('admin'); // No errors!
これで、正しく動くようになり、qwerty
とadmin
以外ではエラーを出すようになった。