結論
Vue.js を TypeScript で書いたときにMap
型の中身を列挙する方法に少しハマったので調べました。
結論としてはArray.from
でMap
をArray
に変換する方法で列挙できます。
調べた理由
Vue.js で TypeScript のMap
型の中身をテンプレートで列挙する際、
コンパイルエラーは起こさず以下の方法ではMap
の中身が表示されませんでした。
<template>
<div id="app">
<ul>
<li v-for="[key, value] in greetMap" :key="key">
key: {{ key }} value: {{ value }}
</li>
</ul>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
@Component
export default class App extends Vue {
private greetMap = new Map([
[1, 'おはよう'],
[2, 'こんにちは'],
[3, 'おやすみ']
]);
}
</script>
Chorme のデベロッパーツールを確認すると以下のように表示されています。
JavaScriptを有効にしないとマップの反復が正しく機能しません。 有効にしてください。
JavaScript は有効になっているので、エラーメッセージが直接の原因ではないようで、
調べてみると JavaScript と TypeScript の仕様の違いが原因でした。
例えば以下のMap<number, string>
のインスタンスをfor of
でそのまま列挙しようとすると、
JavaScript では OK ですが、TypeScript ではコンパイルエラーを起こします。
const greetMap = new Map([
[1, 'おはよう'],
[2, 'こんにちは'],
[3, 'おやすみ']
])
for (const [key, value] of greetMap) { // <- エラー
console.log(`key: ${key} value: ${value}`)
}
タイプ 'Map<number, string>'は配列型または文字列型ではありません。
イテレータの反復を許可するには、コンパイラオプション '--downlevelIteration'を使用します。
StackOverFlow に似た質問を見つけました。
Iterating over Typescript Map
TypeScript でMap
型を列挙する場合、以下の方法でできるそうです。
-
Array.from
でMap
をネストした配列に変換するMap -> [[], [], []]
for (const [key, value] of Array.from(greetMap)) {
console.log(`key: ${key} value: ${value}`)
}
Map.prototype.forEach
greetMap.forEach((value, key) => {
console.log(`key: ${key} value: ${value}`)
})
-
"downlevelIteration": true
+for of
{
"downlevelIteration": true,
}
for (const [key, value] of greetMap) {
console.log(`key: ${key} value: ${value}`)
}
Map
型の中身をテンプレートでv-for
する
Vue のテンプレート内部の式はほぼ JavaScript と互換性を持っているのでArray.from
する方法で表示ができました。
<template>
<div id="app">
<ul>
<!-- Array.fromでネストした配列に変換 -->
<li v-for="[key, value] in Array.from(greetMap)" :key="key">
key: {{ key }} value: {{ value }}
</li>
</ul>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
@Component
export default class App extends Vue {
private greetMap = new Map([
[1, 'おはよう'],
[2, 'こんにちは'],
[3, 'おやすみ']
]);
}
</script>
Angular や React と違い、Vue のテンプレートの型チェックができない弱点により問題解決にちょっとだけ調査が必要でした。
Angular lnguage service や React の tsx の静的型付けとの親和性は高さが羨ましくもありますが、Vue も 3.0 から TypeScript との統合が進んでいくそうなので、テンプレートの型チェックできる未来も近いかもしれません!