🛡️

CDNで読み込んだライブラリもtype safeに扱いたい

に公開
1

こんにちわ、hanetsuki です。
この記事は、htmlファイルに<script />を用いてにcdnやその他ライブラリを読み込んだ際にエラーになってしまうケースがあったので、その時の解決忘備録です。

npm経由ではなく、CDNで読み込まなければならない制約があるケース...ありますよね(?)

やっぱりTypeScriptで書きたい

私は、TypeScriptが好きなので限りなく利用したいと考えています。
しかし何も対させずにVueを扱おうとするとエラーで怒られます。

index.html
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

<div id="app">{{ message }}</div>

<script src="./app.js"></script>
app.ts
const { createApp } = Vue; // ❌ 名前 Vue が見つかりません。

createApp({
  data() {
    return {
      message: 'Hello Vue!'
    };
  }
}).mount('#app');

Vueは、どこにも定義できていないのでTypeScriptがエラーを出すのは当たり前ですね...

では、解決していきましょう。

解決策

@types/vue.d.ts
import type * as _Vue from 'vue';

declare global {
  const Vue: typeof _Vue
}

export {}

**.d.tsを作成します。これにより、プロジェクト全体にグローバルな変数としてVueが利用できるようになります。

余談:windowオブジェクトの場合

googleアナリティクスを扱う上でよく出会うのが、windowを拡張する場面です。
windowを拡張する場合は以下のようにすると良いです。

@types/window.d.ts
declare global {
  interface Window {
    hoge: string[];
    piyo: number;
  }
}

上記のように対応することでwindow.hogeをtsファイルで呼び出したときに型補完が効いた状態で取り扱うことができます。

最後に

今回はCDNをモデルケースにお話を進めましたが、プロジェクトでは独自のSDKなどを取り扱わなければならないという場面が少なからずあります。

今回の方法は、そういったnpm経由では扱えない場面でモダンな開発がしたい!!!型補完を効かせたい!!という方に向けての対応でした。

少しでも助けになれば幸いです。
それではこれにて

Discussion

kohikohi

hanetsuki様はじめまして。

有益な記事をありがとうございます。
こちらの記事のおかげで「❌ 名前 Vue が見つかりません。」を解決することができたのですが、
app.tsをコンパイルしたapp.jsをブラウザからファイル読み込むと「Uncaught ReferenceError: exports is not defined」が発生してしまう状況です。
tsconfig.jsonのmoduleの設定の問題かと思い色々変更してみたのですが、解決に至りませんでした。
以下が詳細な情報ですが、何か思い当たることはないでしょうか。
もし何かあればご教授いただけますと幸いです。

app.tsのファイル

const { createApp } = Vue;

createApp({
  data() {
    return {
      message: 'Hello Vue!'
    };
  }
}).mount('#app');

app.js(コンパイル後のjs)のファイル

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const { createApp } = Vue;
createApp({
    data() {
        return {
            message: 'Hello Vue!'
        };
    }
}).mount('#app');
//# sourceMappingURL=app.js.map

コンパイルの方法

# typescriptをローカルインストール
npm install --save-dev typescript
# 初期設定
npx tsc --init
# app.tsファイルをコンパイル
npx tsc

tsconfig.jsonの内容

{
  // Visit https://aka.ms/tsconfig to read more about this file
  "compilerOptions": {
    // File Layout
    "rootDir": "./src",
    "outDir": "./dist",

    // Environment Settings
    // See also https://aka.ms/tsconfig/module
    "module": "nodenext",
    "moduleResolution": "nodenext",
    "target": "esnext",
    "types": [],
    // For nodejs:
    // "lib": ["esnext"],
    // "types": ["node"],
    // and npm install -D @types/node

    // Other Outputs
    "sourceMap": true,
    "declaration": true,
    "declarationMap": true,

    // Stricter Typechecking Options
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true,

    // Style Options
    // "noImplicitReturns": true,
    // "noImplicitOverride": true,
    // "noUnusedLocals": true,
    // "noUnusedParameters": true,
    // "noFallthroughCasesInSwitch": true,
    // "noPropertyAccessFromIndexSignature": true,

    // Recommended Options
    "strict": true,
    "jsx": "react-jsx",
    "verbatimModuleSyntax": true,
    "isolatedModules": true,
    "noUncheckedSideEffectImports": true,
    "moduleDetection": "force",
    "skipLibCheck": true,
  }
}