Window
の定義の被りについて
根が深い問題です。何らかのモジュールに分かれていればやりようはあるのですが、設計の問題になってくると思います。
現状の同梱のlib.d.ts
もWindow
の定義部分は消してありますが、型指定している箇所を消しているわけではないので厳密な意味では正しくありません。
lib.d.ts
の中身だけWindow
を別名に置き換えてしまう手もあります。Window
の形でwindow
オブジェクトを取得できなくなりますが、ふつうは直接window
でアクセスすると思うので通常の用途なら問題ないと思います。
interface window extends EventTarget, WindowTimers, WindowSessionStorage, WindowLocalStorage, WindowConsole, GlobalEventHandlers, IDBEnvironment, WindowBase64 {
//...
}
//ここの処理はいらないかもです
interface windowConstructor {
prototype: window;
new(): window;
}
//...
declare var top: window;
declare var window: window;
既に存在するクラス内のメソッド/プロパティを書き換える場合
基本的には書かれている通りです。ついでにInterfaceも定義しておくとよいとおもいます。
interface Window_BattleLog{
addItemNameText?(this:Window_BattleLog,itemName:string):void;
}
Window_MenuStatus.prototype.maxCols = function maxCols(){
return 4;
}
//test code
let c: Window_MenuStatus;
c._height = 123;
let d:number = c.maxCols();
TypeScript/ES2015の文法的にも、インスタンスメソッド/プロパティの上書きはこの方法です。
既に存在するクラスに新しいメソッド/プロパティを追加する場合
継承して別のIntefaceを定義しなくてもいけるはずです。
interface Window_BattleLog{
addItemNameText?(this:Window_BattleLog,itemName:string):void;
}
Window_BattleLog.prototype.addItemNameText = function(this:Window_BattleLog, itemName:string):void{
this;
}
//test code
let a:Window_BattleLog;
a._waitCount = 100;
a.addItemNameText("test")
変数の型を更新したい場合
考え方としては3つあると思います。
- 元の型自体を拡張し、変数の型を更新しない
- 変数の使用箇所で型アサーション or
as
で別の型とみなす - タイプガードで型を絞り込み、if文の中だけなどで扱う
上記以外では別の変数を定義する形にするしかないとはおもいます。
1. 元の型自体を拡張し、変数の型を更新しない
例でいうところのGame_System
を拡張したとしても、同名のまま拡張すれば変数側の型定義を更新する必要はありません。前述で提示した形で同名のままクラスを拡張できます。
2. 変数の使用箇所で型アサーション or as
で別の型とみなす
型の拡張を継承でやるならば以下のような方法があります。
class GSEx extends Game_System{
public addedProp = "prop";
}
$gameSystem = new GSEx();
($gameSystem as GSEx).addedProp; //as
(<GSEx>$gameSystem).addedProp; //型アサーション
問題は使用箇所ですべて上記の書き方をしないといけないことです。
3.タイプガードで型を絞り込み、if文の中だけなどで扱う
条件文の中だけですが、絞り込むことで置き換えに近いことができます。
class GSEx1 extends Game_System{
public name = "GSEx1"
}
class GSEx2 extends Game_System{
public name = "GSEx2"
}
class GSEx3 extends Game_System{
public name = "GSEx3"
}
function isGSEx2(gs: typeof $gameSystem):gs is GSEx2{
return gs instanceof GSEx2;
}
$gameSystem = new GSEx2();
if(isGSEx2($gameSystem)){
$gameSystem.name; //ok; GSEx2
}else{
$gameSystem.name; //error; Game_System
}