5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Typescriptでブラウザ用ライブラリを作成する時に困ったこと

Posted at

はじめに

Typescriptがスタンダードになりつつある流れを感じ、勉強がてら既存のライブラリを書き換えようと思ったら、なかなか苦労した話です。

困ったこと

既存のライブラリは、以下のような使い方をします。

use.js
(function(){
    // ライブラリの処理 
    // この中でwindow.Libraryを定義
})();
var setting = {
    text: "text",
    num: 1
};
window.Wapper = window.Wapper || {
    start: function(setting) { 
        window.Library.start(setting);
    }
};

なぜこの様な使い方なのかは、様々な事情があるので、割愛します。

ブラウザのwindowオブジェクトにプロパティを追加したいのですが、typescriptの場合、どのように書けばいいかわからなかったので、色々試してみました。

バージョン

typescriptのバージョンは、3.5.3です。

既存ライブラリの書き方

既存ライブラリは、ES2015で書かれていて、babel+webpackで最終的に1ファイルに出力されます。

index.js
(() => {
    function init(setting) {
        // init処理
    };

    window.Library = window.Library || {
        start: (setting) => {
            init(setting);
        },
    };
})()

Typescriptで書いてみる

とりあえず、ほぼそのまま貼ってみました。

index.ts
(() => {
    function init(setting: any) {
        console.log(setting);
    }

    window.Lib = window.Lib || {
        start: (setting: any) => {
            init(setting);
        }
    }
})();

以下、エラーで怒られました。

Property 'Lib' does not exist on type 'Window'.ts(2339)

WindowにLibなんてないとのことです。
そりゃそうなんですが、どうやって解決するのがググりました。

Typescriptで手っ取り早く外部ライブラリを使う

Interfaceでwindowを定義してやることでエラーが回避できるらしい。

index.ts
interface Window {
    Lib: any;
}

(() => {
    function init(setting: any) {
        console.log(setting);
    }

    window.Lib = window.Lib || {
        start: (setting: any) => {
            init(setting);
        }
    }
})();

一応エラーがでなくなったので、これでコンパイルしてみると、問題なく動きました。

スクリーンショット 2019-07-23 19.55.20.png

webpackとの兼ね合い

一応、上記の方法でwindowオブジェクトにプロパティを追加できたのですが、気になったことが。

webpackには、libraryというオプションがあって、これを使うと同様にwindowオブジェクトにプロパティを追加できます。

module.exports = {
    mode: 'production',
    entry: './src/index.ts',
    output: {
      path: `${__dirname}/lib`,
      filename: 'index.js',
      library: "Lib",
      libraryExport: "default",
      libraryTarget: "umd"
    },
    ・・・

これも有効にした場合、どのように動くのかやってみました。

結果は、問題なく動いたんですが、たぶん、コードでwindowに追加されているので、webpackの設定は、関係なくなっているような気がします。

そこで、コード内でwindowを指定しないように書き直してみました。

index.ts
class Lib {
    init(setting: any) {
        console.log(setting);
    }
}

export default class {
    static start = (setting: any) => {
        const lib: Lib = new Lib();
        lib.init(setting);
    }
}

こんな感じに書き直して、コンパイルを実行。
これも問題なく動きました。

スクリーンショット 2019-07-23 20.10.36.png

まとめ

個人的に、コード内には、windowの記述を書かないで、webpackの設定でプロパティを追加する方法の方がスマートなのかなと思いました。

他にも方法があるのかもしれないのですが、一旦、やりたいことはできたので、よかったです。

後、引数をanyにしていますが、実際にはちゃんと型書いてます。anyは使わないようにしてます。

おまけ

webpackのlibrary設定ですが、コード内にexport defaltの記述があるクラスが存在しないとうまく動かなかったです。

class Lib {
    init(setting: any) {
        console.log(setting);
    }
}

export class Main {
    static start = (setting: any) => {
        const lib: Lib = new Lib();
        lib.init(setting);
    }
}
スクリーンショット 2019-07-23 20.16.55.png

以上です。

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?