import * as M from ""で読み込んだモジュールをブラケット記法[]で使いたい。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//module_a export const contents_a = ...; export const contents_b = ...; export const contents_c = ...; //module_b import * as M from "./module_a" export const someFunc = (name: string) => { M.contents_a; //ドット表記法なら問題ない M[name]; //この書き方はエラー /* expression of type 'string' can't be used to index type 'typeof import("..."). No index signature with a parameter of type 'string' was found on type 'typeof import("..."). ts(7053) */ } |
こんな感じで引数(変数)に対応したモジュールを使いたい場合にどうするか。
リテラル型のunion型で定義する
モジュールにないものにアクセスする可能性があるのでダメなのはわかる。
|
1 2 3 |
(name: "contents_a" | "contents_c" | "contents_c") => { M[name]; } |
リテラルのunion型でコンテンツを列挙すればブラケットでアクセス可能になる。
でもこれだと数が多いときにどうすればいいんだろう。
配列化してunion化する
Object.keys(M)でコンテンツ一覧を配列化できる。
配列からunion型に変換する方法はあるだろうかと調べてみる。
➡TypeScript 3.4 で Array (string[]) を Union Type に変換する Tips
as constでリテラル配列として定義したものをnumberで制御してtypeofでリテラル列挙してる感じだろうか。
Object.keys(M)はas constできないので結局stringになってしまいます。
keyof 演算子(ドキュメント)
Objectなんて使わなくてもkeyofを使えばキー一覧のunion型を得られるらしい。
|
1 2 |
(name: keyof M) => {} //名前空間 'M' を型として使用することはできません。ts(2709) |
import * asで名前空間として定義したので型ではないと怒られる。
typeofをかまして使う。
|
1 |
(name: keyof typeof M) => {} |
これで想定通りの動きになる。
なんとなく見た目は気になるけどシンプルに解決できた。