Calling initSvg() on a Block returned by newBlock() in TypeScript?

56 views
Skip to first unread message

Florian Wörister

unread,
Aug 5, 2025, 3:02:59 PMAug 5
to Blockly

Hi everyone,

I'm currently migrating my project (blocksembler) to TypeScript and have hit a small roadblock with the initSvg() method of the BlockSvg class.

Here’s the relevant snippet:

toBlock(ws: Workspace) {
   let block = ws.newBlock(NopInstruction.getMnemonic());
   block.initSvg();

   return block;
}

The issue: newBlock() returns a Block, which doesn't have the initSvg() method defined. However, as far as I understand, it actually returns an instance of BlockSvg, which does have this method (and extends Block).

What’s the recommended way to handle this?
Should I cast the result to BlockSvg before calling initSvg(), like so:
(block as unknown as BlockSvg).initSvg();

Or is there a cleaner or more idiomatic approach in TypeScript to deal with this kind of situation?

Thanks in advance for your help!

Best wishes,
Florian

Aaron Dodson

unread,
Aug 5, 2025, 3:08:34 PMAug 5
to Blockly
Hi Florian,

Indeed, Workspace.newBlock() returns a Block, but WorkspaceSvg.newBlock() returns a BlockSvg. Your ws arg is typed as Workspace; if this is in fact a rendered workspace, switching that to WorkspaceSvg should resolve this issue, although you may need to work backwards to fix the type of the ws object where this method is called.

I hope that helps - feel free to let me know if you have further questions!

- Aaron

Florian Wörister

unread,
Aug 5, 2025, 3:51:01 PMAug 5
to Blockly

Ah, that makes perfect sense now! I wasn’t aware of the WorkspaceSvg class — thanks for pointing that out.

Really appreciate the quick and helpful response!

Just out of curiosity: are there other workspace representations besides SVG, or is WorkspaceSvg the only one typically used in practice?

Best,
Florian

Aaron Dodson

unread,
Aug 5, 2025, 3:57:24 PMAug 5
to Blockly
Of couse! WorkspaceSvg is the only other representation; as you noted, there is also Block and BlockSvg, Connection and RenderedConnection, and WorkspaceComment and RenderedWorkspaceComment. In all cases, the *Svg/Rendered* classes correspond to a normal visible workspace, and the plain versions to a headless environment; that is to say, if you have a WorkspaceSvg, all the blocks on it will be BlockSvg, and all the connections on the blocks will be RenderedConnection, etc. This allows for Blockly to be used headless/server-side (often for code generation), or in the traditional interactive graphical mode. The naming is unfortunately a bit inconsistent, and while Typescript does have the ability to express the invariant I described about each group of classes implying that references to others are of the class in the same group, we weren't fully able to express that in Blockly's types while maintaining backwards compatibility. As a result, there are a few rough edges that may need a cast, but where possible we've made the types accurate, and you can rely that if you have one of the rendered/SVG variants all the objects it references will likewise be in that group, and vice versa.

- Aaron

Florian Wörister

unread,
Aug 6, 2025, 7:27:04 AMAug 6
to Blockly
Thank you so much! I was already curious about the rationale behind this design, and now it makes perfect sense to me. :)
Reply all
Reply to author
Forward
0 new messages