Skip to content

TS Types: registerBlockType signature not match the @wordpress/create-block scaffolded file invokation #53605

Open

Description

@tresorama

Description

Trying typescript with custom block and some early error stopped coding.
Here is the first "obstacle"

Step-by-step reproduction instructions

  1. Go to /plugins/ with command line
  2. Scaffold a new custom block with npx @wordpress/create-block --variant dynamic my-new-block
  3. Open block.json and ensure that "icon" equal to "smiley" (if not remember what it is and expect that as the correct icon)
  4. Run npm start, launch a Block Editor page and add this block to the page, and check that the icon is correct
  5. Stop dev server
  6. Convert /my-new-block/src/index.js extension to .ts
  7. Install used dependency npm i @wordpress/blocks
  8. Install used dependency typings npm i -D @types/wordpress__blocks
  9. Open index.ts
  10. See the TS error in code editor
    Schermata 2023-08-12 alle 21 40 59

The Error goes away with this procedure:

  1. Right click > Go to Definition on registerBlockStyle invocation (line 28 of screenshot)
    • this should open this file: plugins/my-new-block/node_modules/@types/wordpress__blocks/api/registration.d.ts
    • Get that we are using the overload 2 of the function signature
    • If not using VsCode you must find your way to "see" the type definition of the registerBlockType
  2. Read the TS error on the overload 2:
    • Type '{ edit: () => WPElement; }' is missing the following properties from type 'Pick<Block<{}>, "attributes" | "category" | "title">': attributes, category, title
    • So we miss "attributes", "category", "title"
  3. Mutate index.ts like this
registerBlockType(metadata.name, {
	...metadata,
	edit: Edit,
});
  1. Now the TS error for overload 2 is different:
  • Types of property 'icon' are incompatible.
    Type 'string' is not assignable to type 'BlockIcon | undefined'.
  1. Add also "icon: undefined":
registerBlockType(metadata.name, {
	...metadata,
	icon: undefined,
	edit: Edit,
});
  1. No more error.
  2. Run npm start, launch the Block Editor and look that now the block icon is not present anymore.
  3. Remove the icon: undefined line of step 5
  4. Re-do step 7 and check that icon of the block is now correct again
  5. So icon can be a string, and TS types are wrong
  6. Manually adjust types:
  • in plugins/my-new-block/node_modules/@types/wordpress__blocks/index.d.ts line 326, change
export type BlockConfiguration<T extends Record<string, any> = {}> = Partial<Omit<Block<T>, 'icon'>> &
    Pick<Block<T>, 'attributes' | 'category' | 'title'> & {
        icon?: BlockIcon | undefined;
    };

with

export type BlockConfiguration<T extends Record<string, any> = {}> = Partial<Omit<Block<T>, 'icon'>> &
    Pick<Block<T>, 'attributes' | 'category' | 'title'> & {
        icon?: BlockIcon | string | undefined;
    };
  1. Update index.ts as
registerBlockType(metadata.name, {
	...metadata,
	edit: Edit,
});
  1. Check that everything is ok

Screenshots, screen recording, code snippet

No response

Environment info

  • Wordpress 6.3
  • NO Gutenerberg Plugin

Please confirm that you have searched existing issues in the repo.

Yes

Please confirm that you have tested with all plugins deactivated except Gutenberg.

Yes

Activity

  1. added
    [Type] BugAn existing feature does not function as intended
    on Aug 14, 2023
  2. gziolo commented on Aug 31, 2023

    @gziolo
    Member

    The definition for @wordpress/blocks types isn't maintained in the Gutenberg repository. It is outdated and it should get updated externally until it's tightly integrated with the package.

    In the context of WordPress, it shouldn't be necessary to pass the full metadata object with registerBlockType if the block gets registered on the server with register_block_type pointing to the folder with the block.json file. If there is no block.json registration on the server, then:

    registerBlockType(metadata.name, {
    	...metadata,
    	edit: Edit,
    });

    should be replaced with:

    registerBlockType(metadata, {
    	edit: Edit,
    });
  3. gziolo commented on Aug 31, 2023

    @gziolo
    Member

    There was an attempt started in #48604 to add native support for TypeScript in @wordpress/blocks.

  4. sethstha commented on Jan 23, 2024

    @sethstha

    The issue only occurs when we spread metadata. It treats icon as string from json whereas icon has its own type def

    Just for someone who is struggling like me this is the solution I used for now

    registerBlockType(metadata.name, {
      title: metadata.title,
      description: metadata.description,
      category: metadata.category,
      icon: 'hammer',
      supports: {
        html: metadata.supports.html,
      },
      attributes: null,
      edit: Edit,
    });
    
  5. TonyGravagno commented on Mar 2, 2024

    @TonyGravagno
    Contributor

    The solution by @sethstha should work, with registerBlockType overload 2 and all parameters fed individually.

    But (only reiterating @gziolo here) I think a little less work is required by adding "attributes": {} to blocks.json, and then switching to overload 1 by simply removing the .name parameter. The function will get everything it needs from block.json, and additional settings other than edit and save are no longer necessary unless you want to override block.json (project-specific) defaults.

    To be clear:

    // index.ts
    registerBlockType( metadata, {
    	edit: Edit, // this could be simplified with "import {Edit as edit}"
    	save,
    } );

    block.json:

    {
    	"everything else down to viewScript": "file:./view.js",
    	"attributes": {} // new
    }

    So maybe to help close off this ticket for now, and until things stabilize, app/block developers can add an empty object "attributes" to block.json, and change from overload 2 to overload 1 on registerBlockType.

    I don't want to conflate issues, but since TypeScript was brought up, I wasn't able to get this index file working as index.ts until I came up with the solution I documented here. That is, metadata wouldn't import from block.json until tsconfig.json allowed it ... within the context of this specific project type. YMMV

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    [Feature] BlocksOverall functionality of blocks[Type] BugAn existing feature does not function as intended

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions