ionic(あるいはTypeScript)で既存のjavascriptファイルを取り込んで使いたい場合の例
基本的には以下のサイトを参照する事をお勧めします。
JavaScriptからの移行ガイド
https://typescript-jp.gitbook.io/deep-dive/type-system/migrating
***重要***
参考になる面もあるかと思いますが最終的に予期せぬ挙動を引き起こしたのでご注意ください。
ionicのバージョンアップが原因(正確には作られた設定ファイルの中身)と思われますが、前に作ったプロジェクトではエラーもなく使用できた圧縮・解凍用のjavascriptファイルがエラーが表示されて使用できなくなりました。
ファイル名は以下の通りでオリジナルは20年以上前に最終リリースされた圧縮解凍のコードです。
rawdeflate.js
rawinflate.js
/* Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp>
* Version: 1.0.0.1
* LastModified: Dec 25 1999
*/
エラーの内容は、『モジュール 'src/assets/othercode/rawinflate.js' の宣言ファイルが見つかりませんでした。』と言うもので、要はjavascript内で型宣言(stringとかnumberとか)が無いのでよろしくないという事のようです。
最初は宣言ファイルを作る必要があるのかと暗澹としたのですが、ファイル拡張子を変更して、any型を使ってエラーを抑制する方法もあると知りました。
※注意※
今回は使えない手段ですが、そのjavascriptファイルの型定義ファイルを他の人が作成しているならば、それを取り込めば良いだけのケースもあるようです。例えばjqueryをモジュールとして使用したい場合などは下記の移行ガイドが役に立つと思います。
※注意終了※
参考にしたのは、TypeScript Deep Dive 日本語版 > JavaScriptからの移行ガイドです。
https://typescript-jp.gitbook.io/deep-dive/type-system/migrating
これに従い、ソースコードの拡張子を .jsから.tsに変更しエラーを抑制する方法で解決を試みました。
以下は、VisualStudioCodeでの作業例です。
ステップ1:
javascriptファイルの修正
取り込みたいjavascriptファイルをプロジェクトの適当なフォルダーにコピーし(通常はsrc/assets/以下のどこか)、その拡張子を.jsから.tsに変更すると、そのファイルに多くのエラーが出るかもしれません。
(出ない場合は次のステップに進む)
ただしエラーの種類は、型が未指定の変数をany型にする作業がほとんどで、種類は多くはないと思われます。
今回のファイルで見ると、(拡張子を.tsに変更した)ファイル内のエラー対処は以下のようになりました。(rawinflate.jsの場合。rawdeflate.jsはもう少しエラーの種類が少なかったです。)
1.初期値をセットしていない変数宣言に" : any"を追加して型定義
(=nullをセットしている場合も含む)
2.以下のようなコードの場合、this:anyで対応、型をas anyで対応
---------------------対応前コード---------------------
var zip_HuftList = function() {
this.next = null;
this.list = null;
}
---------------------対応後コード---------------------
var zip_HuftList = function(this:any) {
this.next = null;
this.list = null;
}as any
------------------------------------------------------
3.function()内の引数にも" : any"を追加して型定義。(function内でthisを使っているならば、すべての引数の前に"this:any, "を追加する)
4.エラー:型 'any' を型 'never' に割り当てることはできません。の解決。
解説
エラーにならずに、なおかつ初期値を設定していない変数宣言があると、このようになる模様。
元の変数宣言に" : any"を追加
5.エラー:'q' は 'null' の可能性があります。の解決
解説
qと言う配列をnullで初期化してあったので、[]に変更
---------------------対応前コード---------------------
q = null;
---------------------対応後コード---------------------
q = [];
------------------------------------------------------
6.エラー:'if' ステートメントの本文を空のステートメントにすることはできません。の解決
コメント化するしかない
7.エラー:型 'typeof globalThis' にはインデックス シグネチャがないため、要素は暗黙的に 'any' 型になります。の解決
ここまでのエラー修正は、まあ、なんとなくそうだろうな的に理解している範囲でしたが、このエラーは知識のない範囲で起きている事はすぐにわかりました。
ですので、謎に挑戦のつもりで挑みます。
まず、このエラーは最後の部分の以下のコードで起きています。
---------------------エラーのコード---------------------
if (! ctx.RawDeflate) ctx.RawDeflate = {};
ctx.RawDeflate.inflate = zip_inflate;
---------------------エラーのコード終了-----------------
".RawDeflate"の部分がエラーで、原因としては、その直前の"ctx"が型 'typeof globalThis'なので、こういう書き方は出来ないよ!という事のようです。
"ctx"の初出は、先頭の"(function(ctx){"で、ここで型指定をしていないために"ctx"が型 'typeof globalThis' と見なされ、プロパティ"RawDeflate"の使用が間違っているという事のようです。
という事は"(function(ctx){"の"ctx"に適切な型を指定してやれば動くと思われます。
従って、ファイルの先頭で以下の型定義を指定
------------------------------------------
type ObjType = {
"RawDeflate": {"inflate":any};
};
------------------------------------------
さらにctxに上の型を定義
------------------------------------------
(function(ctx:ObjType){
------------------------------------------
8.7.の修正をすると末尾でエラーが発生するが以下のように"as any"をつけてエラー修正
---------------------修正前コード---------------------
})(this);
---------------------修正後コード---------------------
})(this as any);
------------------------------------------------------
以上でこのファイル単体のエラーは(とりあえず)消えました。
続いて、ステップ2でこのファイルのimport可能にします。
ステップ2:
現時点では、上記ファイルをimportするhome.page.ts側で以下のようなエラーが起こります。
------------------------------------------
ファイル 'c:/MyTest/gamebook/src/assets/othercode/rawinflate.ts' はモジュールではありません。
------------------------------------------
これはある意味当然でexportキーワードが無い事が原因でしょう。
追加で宣言したタイプ宣言の下の、当初の先頭文を以下のように修正しました。
---------------------修正前コード---------------------
(function(ctx:ObjType){
中略
})(this);
---------------------修正後コード---------------------
export default(function(ctx:ObjType){
中略
}(this);
------------------------------------------------------
function(){}を囲む"()"を外したのは、rawinflate.tsで以下のエラーが出たためです。(rawdeflate.tsでは出ない)
TypeError: ctx is undefined
対処として参考にしたのは以下のサイトです。
export defaultでimport fromした関数のエラー対処法:TypeError: Object is not a function, [Vue warn]: Error in render
https://prograshi.com/language/javascript/error-object-is-not-a-function/
とりあえず、rawinflate.tsとrawdeflate.tsのどちらも"()"を外した形でImport成功しました。
実装テストとして、以下のようなコードを試して問題なく動作する事を確かめました。
let str0="主よ、いずこへ?";//元の文章
let str1=this.fnCompress(str0);//圧縮した文章
let str2=this.fnUnCompress(str1)//解凍した文章
alert(str0+"\n"+str1+"\n"+str2)
結果
主よ、いずこへ?
JUU0JUI4JUJCJUUzJTgyJTg4JUUzJTgwJTgxJUUzJTgxJTg0JUUzJTgxJTlBJUUzJTgxJTkzJUUzJTgxJUI4JTNG
主よ、いずこへ?
元の文章が短いためか、本当に圧縮されたのか?という結果ではありますが、動いているようには見えます。念のために、.jsをそのまま使った別の以前に作ったプロジェクトで試すと・・・・
結果
主よ、いずこへ?
U3U1UXWyUHVyUnU1VrUwUrWwADMMVC0MwQxDVQsTKMPSEcYwhjKAGo3dAA==
主よ、いずこへ?
明らかに結果が違いますね。
ざっと見たところ、解決できる可能性はあるものの、別のTypescript用のライブラリーを探す方が建設的と判断しました。
経験と言う点では役に立ちましたが圧縮解凍機能は後回しにいたします。
投稿