RPG Maker MZ Typescript edition

RaiderSoap

Researcher
Member
Joined
Mar 30, 2016
Messages
6
Reaction score
1
First Language
Mandarin
Primarily Uses
RMMZ
I use tsc with the following config to generate declarations, not all files works. For example, when generating 'Tilemap.js' it gives me errors.
JSON:
{
  "include": ["src/**/*"],
  "compilerOptions": {
    "allowJs": true,
    "declaration": true,
    "emitDeclarationOnly": true,
    "outDir": "dist",
  },
}
Here is the raw output generated from Bitmap.js, as we can see, a lot of constructor args became any, and other types that can't be inferred became any too. First of all, we definitely need to get rid of the double declaration, fixing the static methods, and manually put 'private/protected' to private fields. So this is not a 100% automatic solution to do everything for us, but I think it is a good starting point. And most importantly, it is complete, we won't miss any function, or miss type something (I noticed some typos in the repo).

JavaScript:
/**
* The basic object that represents an image.
*
* @class
* @param {number} width - The width of the bitmap.
* @param {number} height - The height of the bitmap.
*/
declare function Bitmap(...args: any[]): void;
declare class Bitmap {
    /**
     * The basic object that represents an image.
     *
     * @class
     * @param {number} width - The width of the bitmap.
     * @param {number} height - The height of the bitmap.
     */
    constructor(...args: any[]);
    initialize(width: any, height: any): void;
    _canvas: HTMLCanvasElement;
    _context: CanvasRenderingContext2D;
    _baseTexture: any;
    _image: HTMLImageElement;
    _url: string;
    _paintOpacity: number;
    _smooth: boolean;
    _loadListeners: any[];
    _loadingState: string;
    /**
     * The face name of the font.
     *
     * @type string
     */
    fontFace: string;
    /**
     * The size of the font in pixels.
     *
     * @type number
     */
    fontSize: number;
    /**
     * Whether the font is bold.
     *
     * @type boolean
     */
    fontBold: boolean;
    /**
     * Whether the font is italic.
     *
     * @type boolean
     */
    fontItalic: boolean;
    /**
     * The color of the text in CSS format.
     *
     * @type string
     */
    textColor: string;
    /**
     * The color of the outline of the text in CSS format.
     *
     * @type string
     */
    outlineColor: string;
    /**
     * The width of the outline of the text.
     *
     * @type number
     */
    outlineWidth: number;
    isReady(): boolean;
    isError(): boolean;
    get url(): string;
    get baseTexture(): any;
    get image(): HTMLImageElement;
    get canvas(): HTMLCanvasElement;
    get context(): CanvasRenderingContext2D;
    get width(): number;
    get height(): number;
    get rect(): Rectangle;
    set smooth(arg: boolean);
    get smooth(): boolean;
    set paintOpacity(arg: number);
    get paintOpacity(): number;
    destroy(): void;
    resize(width: number, height: number): void;
    blt(source: Bitmap, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw?: number, dh?: number): void;
    getPixel(x: number, y: number): string;
    getAlphaPixel(x: number, y: number): string;
    clearRect(x: number, y: number, width: number, height: number): void;
    clear(): void;
    fillRect(x: number, y: number, width: number, height: number, color: string): void;
    fillAll(color: string): void;
    strokeRect(x: number, y: number, width: number, height: number, color: string): void;
    gradientFillRect(x: number, y: number, width: number, height: number, color1: string, color2: string, vertical: boolean): void;
    drawCircle(x: number, y: number, radius: number, color: string): void;
    drawText(text: string, x: number, y: number, maxWidth: number, lineHeight: number, align: string): void;
    measureTextWidth(text: string): number;
    addLoadListener(listner: Function): void;
    retry(): void;
    _makeFontNameText(): string;
    _drawTextOutline(text: any, tx: any, ty: any, maxWidth: any): void;
    _drawTextBody(text: any, tx: any, ty: any, maxWidth: any): void;
    _createCanvas(width: any, height: any): void;
    _ensureCanvas(): void;
    _destroyCanvas(): void;
    _createBaseTexture(source: any): void;
    _updateScaleMode(): void;
    _startLoading(): void;
    _startDecrypting(): void;
    _onXhrLoad(xhr: any): void;
    _onLoad(): void;
    _callLoadListeners(): void;
    _onError(): void;
}
declare namespace Bitmap {
    function load(url: string): Bitmap;
    function snap(stage: Stage): Bitmap;
}
The attachment is all (except Tilemap.d.ts and Graphics.js, as mention they give me errors) .d.ts of the core API
 

Attachments

Last edited:

nio kasgami

VampCat
Veteran
Joined
May 21, 2013
Messages
8,949
Reaction score
3,039
First Language
French
Primarily Uses
RMMV
I use tsc with the following config to generate declarations, not all files works. For example, when generating 'Tilemap.js' it gives me errors.
JSON:
{
  "include": ["src/**/*"],
  "compilerOptions": {
    "allowJs": true,
    "declaration": true,
    "emitDeclarationOnly": true,
    "outDir": "dist",
  },
}
Here is the raw output generated from Bitmap.js, as we can see, a lot of constructor args became any, and other types that can't be inferred became any too. First of all, we definitely need to get rid of the double declaration, fixing the static methods, and manually put 'private/protected' to private fields. So this is not a 100% automatic solution to do everything for us, but I think it is a good starting point. And most importantly, it is complete, we won't miss any function, or miss type something (I noticed some typos in the repo).

JavaScript:
/**
* The basic object that represents an image.
*
* @class
* @param {number} width - The width of the bitmap.
* @param {number} height - The height of the bitmap.
*/
declare function Bitmap(...args: any[]): void;
declare class Bitmap {
    /**
     * The basic object that represents an image.
     *
     * @class
     * @param {number} width - The width of the bitmap.
     * @param {number} height - The height of the bitmap.
     */
    constructor(...args: any[]);
    initialize(width: any, height: any): void;
    _canvas: HTMLCanvasElement;
    _context: CanvasRenderingContext2D;
    _baseTexture: any;
    _image: HTMLImageElement;
    _url: string;
    _paintOpacity: number;
    _smooth: boolean;
    _loadListeners: any[];
    _loadingState: string;
    /**
     * The face name of the font.
     *
     * @type string
     */
    fontFace: string;
    /**
     * The size of the font in pixels.
     *
     * @type number
     */
    fontSize: number;
    /**
     * Whether the font is bold.
     *
     * @type boolean
     */
    fontBold: boolean;
    /**
     * Whether the font is italic.
     *
     * @type boolean
     */
    fontItalic: boolean;
    /**
     * The color of the text in CSS format.
     *
     * @type string
     */
    textColor: string;
    /**
     * The color of the outline of the text in CSS format.
     *
     * @type string
     */
    outlineColor: string;
    /**
     * The width of the outline of the text.
     *
     * @type number
     */
    outlineWidth: number;
    isReady(): boolean;
    isError(): boolean;
    get url(): string;
    get baseTexture(): any;
    get image(): HTMLImageElement;
    get canvas(): HTMLCanvasElement;
    get context(): CanvasRenderingContext2D;
    get width(): number;
    get height(): number;
    get rect(): Rectangle;
    set smooth(arg: boolean);
    get smooth(): boolean;
    set paintOpacity(arg: number);
    get paintOpacity(): number;
    destroy(): void;
    resize(width: number, height: number): void;
    blt(source: Bitmap, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw?: number, dh?: number): void;
    getPixel(x: number, y: number): string;
    getAlphaPixel(x: number, y: number): string;
    clearRect(x: number, y: number, width: number, height: number): void;
    clear(): void;
    fillRect(x: number, y: number, width: number, height: number, color: string): void;
    fillAll(color: string): void;
    strokeRect(x: number, y: number, width: number, height: number, color: string): void;
    gradientFillRect(x: number, y: number, width: number, height: number, color1: string, color2: string, vertical: boolean): void;
    drawCircle(x: number, y: number, radius: number, color: string): void;
    drawText(text: string, x: number, y: number, maxWidth: number, lineHeight: number, align: string): void;
    measureTextWidth(text: string): number;
    addLoadListener(listner: Function): void;
    retry(): void;
    _makeFontNameText(): string;
    _drawTextOutline(text: any, tx: any, ty: any, maxWidth: any): void;
    _drawTextBody(text: any, tx: any, ty: any, maxWidth: any): void;
    _createCanvas(width: any, height: any): void;
    _ensureCanvas(): void;
    _destroyCanvas(): void;
    _createBaseTexture(source: any): void;
    _updateScaleMode(): void;
    _startLoading(): void;
    _startDecrypting(): void;
    _onXhrLoad(xhr: any): void;
    _onLoad(): void;
    _callLoadListeners(): void;
    _onError(): void;
}
declare namespace Bitmap {
    function load(url: string): Bitmap;
    function snap(stage: Stage): Bitmap;
}
I see I will try to do so to generate some of the classic method but ill get busy so I dunno if I can work much on it. it indeed simplify our works.
You can pull request the SRC I will work on a function or a 'command' that allow us to extract specific class
still wish we had a way to split the Core files into separate files so we can work on separate file easier tbh
if anyone have an idea how to split Javascript files into separate files so it's easier for us to work.
 

RaiderSoap

Researcher
Member
Joined
Mar 30, 2016
Messages
6
Reaction score
1
First Language
Mandarin
Primarily Uses
RMMZ
I see I will try to do so to generate some of the classic method but ill get busy so I dunno if I can work much on it. it indeed simplify our works.
You can pull request the SRC I will work on a function or a 'command' that allow us to extract specific class
still wish we had a way to split the Core files into separate files so we can work on separate file easier tbh
if anyone have an idea how to split Javascript files into separate files so it's easier for us to work.
I simply copy paste them into sperate files, not very smart :confused:
 

Ghost314

Villager
Member
Joined
Aug 13, 2020
Messages
15
Reaction score
12
First Language
English
Primarily Uses
RMMZ
I'll take a look at it when I have time, I also need to ask a general question though.

Suppose we have a class hierarchy where class B extends class A (A is the super class). Then we have a method X that accepts parameter Y, and calls a method declared in class A on parameter Y. However when looking at all the places in the code where someone calls X, we can see that instances of B are the only thing ever passed to X.

Should we declare the parameter Y to be of type A (the super class) so that plugin code can call it with their own sub-classes of A? Or should we declare the parameter Y to be of type B so that plugin code can extend method X and access all the fields of B?
 

nio kasgami

VampCat
Veteran
Joined
May 21, 2013
Messages
8,949
Reaction score
3,039
First Language
French
Primarily Uses
RMMV
I'll take a look at it when I have time, I also need to ask a general question though.

Suppose we have a class hierarchy where class B extends class A (A is the super class). Then we have a method X that accepts parameter Y, and calls a method declared in class A on parameter Y. However when looking at all the places in the code where someone calls X, we can see that instances of B are the only thing ever passed to X.

Should we declare the parameter Y to be of type A (the super class) so that plugin code can call it with their own sub-classes of A? Or should we declare the parameter Y to be of type B so that plugin code can extend method X and access all the fields of B?
it is possible to do 'overloading' in typescript

TypeScript provides the concept of function overloading. You can have multiple functions with the same name but different parameter types and return type. However, the number of parameters should be the same.

Example: Function Overloading
Copy
function add(a:string, b:string):string;

function add(a:number, b:number): number;

function add(a: any, b:any): any {
return a + b;
}

add("Hello ", "Steve"); // returns "Hello Steve"
add(10, 20); // returns 30
so if you think you want to pass the parameter it is possible do remember that if the original code doesn't pass the parameter to the super then it will not work.

Generally in the instance, it will work.
 

Ghost314

Villager
Member
Joined
Aug 13, 2020
Messages
15
Reaction score
12
First Language
English
Primarily Uses
RMMZ
As long as we're messing around with tsc, I'm going to link an article I found: https://dev.to/open-wc/generating-typescript-definition-files-from-javascript-5bp2

They talk about using tsc along with jsdoc comments to generate a more complete set of .d.ts files for a .js library. It seems you can also get compile time type-checking on that .js library using this method, as .tsc is capable of using the jsdoc comments to discover types.

It makes me wonder if we can maybe get tsc to use our .d.ts files to type check the original .js files, which could help us find any mistakes we might have made.
 

Kino

EIS Game Dev
Veteran
Joined
Nov 27, 2015
Messages
552
Reaction score
789
First Language
English
Primarily Uses
RMMV
Yes you can and it's what we did for MV previously.
 

nio kasgami

VampCat
Veteran
Joined
May 21, 2013
Messages
8,949
Reaction score
3,039
First Language
French
Primarily Uses
RMMV
yeah @Kino isn't a masochist like me who do hand typing the whole code lol.

but yeah il be busy but I will try to push te change more frequently
their's also section it was impossible for me to finish since it needed the typing of another class.
but it's slowly progressing!
 

Ghost314

Villager
Member
Joined
Aug 13, 2020
Messages
15
Reaction score
12
First Language
English
Primarily Uses
RMMZ
I managed to finish a first draft of the type declaration files for the window classes, so I started looking deeper into how to compile the RMMZ javascript files with typescript to emit declaration files. The main error I kept getting was TS9005, so I asked a question on stack overflow and got some more information on what it means: https://stackoverflow.com/questions/63653098/where-can-i-find-a-tsc-errors-list. I then tried deleting everything in the core javascript file except for the Graphics and FPSCounter classes.

After some additional experimentation I believe I have found the root of the problem. I created the following .js file that mirrors what I think, is the problem code in the core file:

JavaScript:
/**
 * The outer static class.
 *
 * @namespace
 */
function SomeClass() {
    throw new Error("This is a static class");
}

SomeClass.NestedClass = function() {
    this.initialize(...arguments);
};

SomeClass.NestedClass.prototype.initialize = function() {
    this.x = 5;
};
It produces the same sort of error on the function SomeClass() line of code, saying it can't be exported because of private name 'NestedClass'. I noticed when trying to manually add the FPSCounter class declaration to the existing Graphics class declaration in the repo, that having a nested class in a typescript declaration file is a bit of a problem.

A commonly suggested work-around is to have the outer class represented as a namespace and make the nested class a class within that namespace. This explains why there's a jsdoc comment with a namespace annotation above the Graphics function in the original code. For some reason though, that doesn't seem to be resolving the issue.

Anyone have any ideas on where to go from here? If not I may just ask stack overflow again, since a simple example like this is the sort of thing they like to work with.
 

nio kasgami

VampCat
Veteran
Joined
May 21, 2013
Messages
8,949
Reaction score
3,039
First Language
French
Primarily Uses
RMMV
Hey sorry guys I have been busy with work recently.
So far ill try to work on files Also I am talking with someone for helping to create an NPM package.
 

nio kasgami

VampCat
Veteran
Joined
May 21, 2013
Messages
8,949
Reaction score
3,039
First Language
French
Primarily Uses
RMMV
@Ghost314 @RaiderSoap I updated the github to contain the file you did for compiling. I am working on a way to splits the files per class. Webstorm per say have an way of doing it but it's manual.

Although dekita wrote an quick plugin to split the core files.
 

nio kasgami

VampCat
Veteran
Joined
May 21, 2013
Messages
8,949
Reaction score
3,039
First Language
French
Primarily Uses
RMMV
great new ! me and Brandt reworked (well mainly brandt) the typescript structure so now it works in a more cleaner manner + it's now possible to use it as an npm packages! It's also no more dependent of Rollup.js so it can be used with any build tool.

thanks Brandt xD
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts

I'm going to schedule my shuttle to the train station today... after I vote. It's not a pleasant thing to do, since I hate politics. So much negative talk. I can see why it's not allowed here. But about the shuttle. My county has a service called PalmTran, and it's really convenient. They pick you up at your home and drop you off where you need to be. Just give them a date and time.
Titlescreen idle movie player, play some videos if the player sits on the titlescreen too long! [free plugin]
"Alert, alert, there is nothing there. Wake up, there is nothing there. This is not a drill, there is nothing there. Oh hey, I see you're awake early on your day off, let's go for a run."~if dogs could talk.
I love October. It starts out with a lighthearted chillvibes. Near the end of the month, it becomes somewhat dreamy and the days feel slower. Maybe because October is the beginning of rainy season in my country. :D
Ami
--- Surprise Part 2 ---

F.Healer: Look,i'm the Cute White Ghost!
F.Mage: And,im the Scary Witch!
M.Archer: I'm The Handsome Vampire!
M.Fighter: AWOOOOOOO!!!
(Suddenly,The Electricity Is Turned Off. Then Turned On 10 Seconds Later)
Hero: (With Scream Mask & Bloody Knife) Hey,how about my Costume?
Entire Party: (Screaming Until Faint)

Forum statistics

Threads
104,505
Messages
1,006,782
Members
136,009
Latest member
Jaeger
Top