Skip to content

Conversation

Piccirello
Copy link
Member

@Piccirello Piccirello commented Sep 7, 2025

This PR convert all JS in src/webui/www/private/scripts to TS. The typechecking isn't super strict yet (it allows implicit any), but this gives us a good starting point. From here, we can then export strict types from all of our modules (i.e. window.qBittorrent.* classes).

To serve as an example of strict module typing, a few modules have been modified to properly export their types. This includes AddTorrent, Cache, ColorScheme, ContextMenu, FileTree and Misc. All usage of window.qBittorrent.$MODULE is type checked.

@Piccirello Piccirello added the WebUI WebUI-related issues/changes label Sep 7, 2025
@Piccirello Piccirello force-pushed the typescript branch 3 times, most recently from ad2e176 to 662bfe1 Compare September 8, 2025 00:14
js-beautify doesn't support TS and mangles some of the type definitions.
@Piccirello Piccirello marked this pull request as ready for review September 8, 2025 02:02
@Piccirello Piccirello requested a review from a team September 8, 2025 02:02
Copy link
Contributor

@HanabishiRecca HanabishiRecca left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a chunky one. Not sure if it's a good idea to introduce so many changes here (including functional ones), as it could be too difficult to comprehend for reviewers.

Comment on lines +307 to +316
type ElementTypeMap = {
input: HTMLInputElement;
select: HTMLSelectElement;
image: HTMLImageElement;
button: HTMLButtonElement;
ul: HTMLUListElement;
li: HTMLLIElement;
frame: HTMLIFrameElement;
template: HTMLTemplateElement;
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is default HTMLElementTagNameMap type.

Comment on lines +318 to +320
const getElementById = <T extends keyof ElementTypeMap>(id: string, type: T): ElementTypeMap[T] => {
return document.getElementById(id) as ElementTypeMap[T];
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not safe, document.getElementById returns null if element doesn't exist.
Do we have a contract that all used elements would always exist?

Generally speaking, it's better to avoid as casts when possible. This case would require a runtime check though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is meant to be a direct replacement for existing code that calls document.getElementById(). The existing code always assumes the requested element exists, so this new code keeps that behavior. In the future I think it would be useful to refactor that.

@Piccirello
Copy link
Member Author

That's a chunky one. Not sure if it's a good idea to introduce so many changes here (including functional ones), as it could be too difficult to comprehend for reviewers.

This was intended to be as few changes as necessary to get TS compilation working with any amount of type safety. The only large-ish refactor was introducing getElementById, and that was just to avoid introducing 100+ type casts throughout the code.

@HanabishiRecca
Copy link
Contributor

But tsc produces results regardless of errors, unless you explicitly set noEmitOnError.

My proposal was to (at least initially) keep all type checking stuff purely on the dev's side.
I.e. during build we could run tsc --noResolve --noCheck or some other faster transpiler without type checking like esbuild.

@Piccirello
Copy link
Member Author

Piccirello commented Sep 8, 2025

But tsc produces results regardless of errors, unless you explicitly set noEmitOnError.

My proposal was to (at least initially) keep all type checking stuff purely on the dev's side. I.e. during build we could run tsc --noResolve --noCheck or some other faster transpiler without type checking like esbuild.

I don't think there's any point in using TS if we allow type errors. CI should enforce that there aren't any type errors in order to merge. I can break up the current PR if it's easier to review, but I do think these changes are ultimately necessary.

@HanabishiRecca
Copy link
Contributor

I'm talking about primary build script. End users / packagers should not hit that IMO.
For CI type check could be set up as a separate action.

@Piccirello
Copy link
Member Author

I'm talking about primary build script. End users / packagers should not hit that IMO. For CI type check could be set up as a separate action.

I'm not completely following. How would the primary build script differ? And how would we enforce "no new type issues" in CI if we already have ~700 type issues?

@HanabishiRecca
Copy link
Contributor

And how would we enforce "no new type issues" in CI if we already have ~700 type issues?

As I said, we simply don't enforce it for now. Check locally, submit.
Most people would also see errors inside their IDE.

But if you insist on enforcing it, I'm not in a position to argue 🙂

@Piccirello
Copy link
Member Author

@Chocobo1 do you have any thoughts on this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

WebUI WebUI-related issues/changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants