LoginSignup

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

More than 5 years have passed since last update.

Re: ツクールMVのスクリプトをTypeScriptで書いてみませんか?

Posted at

Windowの定義の被りについて

根が深い問題です。何らかのモジュールに分かれていればやりようはあるのですが、設計の問題になってくると思います。

現状の同梱のlib.d.tsWindowの定義部分は消してありますが、型指定している箇所を消しているわけではないので厳密な意味では正しくありません。

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つあると思います。

  1. 元の型自体を拡張し、変数の型を更新しない
  2. 変数の使用箇所で型アサーション or asで別の型とみなす
  3. タイプガードで型を絞り込み、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
}
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