The sky is the limit

Vue.js、PHP、Java、Cordova、Monacaを中心にハイブリッドアプリ開発、PWA開発など効率的なWEB、iOS、Androidアプリ開発の情報を共有します。

【Vue.js】TSとVue.jsを書く場合に、$refsへの参照でエラーとなる【TypeScript】

【Vue.js】TSとVue.jsを書く場合に、$refsへの参照でエラーとなる【TypeScript】

f:id:duo-taro100:20160218004611p:plain

実装した内容

要素の高さを取得したかったので、Vueの$refを使いました。
取得したい要素に、ref属性をつけることでその要素の情報を取得することができます。

html側
<div>
    <p ref="test">テストです</p>
</div>
ts側のコンポーネント
})
export default class TestVue extends Vue {
    mounted(){
        // ref名「test」で取得する
        var testRef = this.$refs.test;
        // 取得できなかったら何もしない
        if(!testRef){
            return;
        }
        // 要素の高さを出力
        console.log(testRef.clientHeight);
    }

上記の実装では、以下のようなエラーとなります。

エラーの内容(コンソール)

error TS2339: Property 'clientHeight' does not exist on type 'Vue | Element | Vue | Element'.
Property 'clientHeight' does not exist on type 'Vue'.

エラーの内容(TS)

[ts]
プロパティ 'clientHeight' は型 'Vue | Element | Vue | Element' に存在しません。
プロパティ 'clientHeight' は型 'Vue' に存在しません。

要するに、

this.$refs.test

は「Vue型」であり、「Vue型」には「clientHeight」というプロパティが存在しないという内容です。

解決策

「型」に問題があるので、キャストすればいいのかなと思い、以下のようしました。

})
export default class TestVue extends Vue {
    mounted(){
        // ref名「test」で取得する
        // 型にanyを指定
        var testRef:any = this.$refs.test;

        // 取得できなかったら何もしない
        if(!testRef){
            return;
        }
        // 要素の高さを出力
        console.log(testRef.clientHeight);
    }

testRef:any

のように、型をanyにしたらできました。
ただし、想定外の型がきた場合などを考慮するとイケテないですね。。。
ということでもっといい方法がないか探しました。

もっといい方法

teratail.com

こちらに記載のあったように修正しました。

})
export default class TestVue extends Vue {
    mounted(){
        // タイプガード Element型かどうか判断する
        const isElement = (x: any): x is Element => x instanceof Element;

       
        // desc_areaを取得
        const { test } = this.$refs;
        
        // Element型かどうか
        // Element以外は何もしない
        if (!isElement(test)) return;

        // 要素の高さを出力
        console.log(test.clientHeight);
    }


tsっぽい書き方に慣れていない私には新鮮ですが、スマートに見えます。
以上です。