Vue で空文字が Prop で渡ってきてバグってしまった話

目次

はじめに

数年前に作られていた vue 2 (TypeScript なし) のプロダクトで空文字が Prop で渡ってきてバグってしまった話と、注意点を備忘録として残します。

背景

数年前に作られていた vue 2 (TypeScript なし) のプロダクトで下記のようなコンポーネントがありました。
  export default {
    props: {
      sample: Boolean,
      default: false,
    },
  };
このコンポーネントはこのように呼び出されています。
<template>
  <Sample :sample="sample2" />
</template>
この sample2、実は文字列が入っていました!! 設計者の意図としては、JS の暗黙的な型変換と同様に空文字列であれば false, 1文字以上であれば true という実装にしたかったのだと思います。

空文字列 "" が true !?

ある日、 sample2 に空文字列 "" が入ってきました。しかし、 Sample が false の場合の挙動をしません。
なんと、 空文字 "" が入ってきたときに コンポーネント内で false に変換されていたのです。
空文字 "" は JavaScript の真偽判定において Falsy になるのでしばらく原因を理解するのに時間かかりました 😢
Falsy (偽値) - MDN Web Docs 用語集: ウェブ関連用語の定義 | MDN
https://developer.mozilla.org/ja/docs/Glossary/Falsy
原因は、v-bind において、 falsy な値は null, undefined, false だけという仕様があるためです。
Migration from Vue 1.x — Vue.js
https://v2.vuejs.org/v2/guide/migration.html#Truthiness-Falsiness-with-v-bind-changed

なぜ

HTML Attribute と同じ挙動になるように揃えたみたいです。個人的には React (JSX) と同じ挙動なのでわかりやすく感じます。 v-if などは引き続き JavaScript の真偽判定と同様の挙動をするようです。

まとめ

  • そもそも boolean な prop に文字列を渡さないようにしよう
  • このようなプログラムを書かれないように規約を設けるという意味でも TypeScript は必須ですね

シェア

Twitter
Facebook
はてブ
LinkedIn
LINE
Pocket