定数に対して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以外ではエラーを出すようになった。