diff --git a/packages/blocks/README.md b/packages/blocks/README.md
index 8c277868a03321..e04239e0e78c75 100644
--- a/packages/blocks/README.md
+++ b/packages/blocks/README.md
@@ -607,7 +607,31 @@ _Parameters_
### registerBlockType
-Undocumented declaration.
+Registers a new block provided a unique name and an object defining its behavior. Once registered, the block is made available as an option to any editor interface where blocks are implemented.
+
+For more in-depth information on registering a custom block see the [Create a block tutorial](https://developer.wordpress.org/block-editor/getting-started/create-block/).
+
+_Usage_
+
+```js
+import { __ } from '@wordpress/i18n';
+import { registerBlockType } from '@wordpress/blocks';
+
+registerBlockType( 'namespace/block-name', {
+ title: __( 'My First Block' ),
+ edit: () =>
{ __( 'Hello from the editor!' ) }
,
+ save: () => Hello from the saved content!
,
+} );
+```
+
+_Parameters_
+
+- _blockNameOrMetadata_ `string | BlockConfiguration< Attributes >`: Block type name or its metadata.
+- _settings_ `Partial< BlockConfiguration< Attributes > >`: Block settings.
+
+_Returns_
+
+- `BlockType | undefined`: The block, if it has been successfully registered; otherwise `undefined`.
### registerBlockVariation
diff --git a/packages/compose/README.md b/packages/compose/README.md
index 0908e8e559948c..57d1ed4fb53056 100644
--- a/packages/compose/README.md
+++ b/packages/compose/README.md
@@ -394,17 +394,17 @@ _Returns_
### useInstanceId
-Provides a unique instance ID.
+Specify the useInstanceId _function_ signatures.
-_Parameters_
+More accurately, useInstanceId distinguishes between three different signatures:
-- _object_ `object`: Object reference to create an id for.
-- _prefix_ `[string]`: Prefix for the unique id.
-- _preferredId_ `[string | number]`: Default ID to use.
+1. When only object is given, the returned value is a number
+2. When object and prefix is given, the returned value is a string
+3. When preferredId is given, the returned value is the type of preferredId
-_Returns_
+_Parameters_
-- `string | number`: The unique instance id.
+- _object_ `object`: Object reference to create an id for.
### useIsomorphicLayoutEffect
diff --git a/packages/docgen/lib/get-intermediate-representation.js b/packages/docgen/lib/get-intermediate-representation.js
index 9f49fc4d4f93a2..05705718e8d9b5 100644
--- a/packages/docgen/lib/get-intermediate-representation.js
+++ b/packages/docgen/lib/get-intermediate-representation.js
@@ -15,6 +15,15 @@ const hasClassWithName = ( node, name ) =>
const hasFunctionWithName = ( node, name ) =>
node.type === 'FunctionDeclaration' && node.id.name === name;
+const hasTSDeclareFunction = ( node, name ) =>
+ node.type === 'TSDeclareFunction' && node.id?.name === name;
+
+const hasImplementationWithName = ( node, name ) =>
+ hasFunctionWithName( node, name ) ||
+ ( node.type === 'ExportNamedDeclaration' &&
+ node.declaration &&
+ hasFunctionWithName( node.declaration, name ) );
+
const hasVariableWithName = ( node, name ) =>
node.type === 'VariableDeclaration' &&
node.declarations.some( ( declaration ) => {
@@ -32,6 +41,8 @@ const hasNamedExportWithName = ( node, name ) =>
node.type === 'ExportNamedDeclaration' &&
( ( node.declaration && hasClassWithName( node.declaration, name ) ) ||
( node.declaration && hasFunctionWithName( node.declaration, name ) ) ||
+ ( node.declaration &&
+ hasTSDeclareFunction( node.declaration, name ) ) ||
( node.declaration && hasVariableWithName( node.declaration, name ) ) );
const hasImportWithName = ( node, name ) =>
@@ -91,19 +102,27 @@ const getJSDoc = ( token, entry, ast, parseDependency ) => {
return (
hasClassWithName( node, entry.localName ) ||
hasFunctionWithName( node, entry.localName ) ||
+ hasTSDeclareFunction( node, entry.localName ) ||
hasVariableWithName( node, entry.localName ) ||
hasNamedExportWithName( node, entry.localName ) ||
hasImportWithName( node, entry.localName )
);
} );
- if ( candidates.length !== 1 ) {
+ if ( candidates.length === 0 ) {
return doc;
}
- const node = candidates[ 0 ];
- if ( isImportDeclaration( node ) ) {
- doc = getJSDocFromDependency( node, entry, parseDependency );
- } else {
- doc = getJSDocFromToken( node );
+ const implementationNode = candidates.find( ( node ) =>
+ hasImplementationWithName( node, entry.localName )
+ );
+ for ( const node of candidates ) {
+ if ( isImportDeclaration( node ) ) {
+ doc = getJSDocFromDependency( node, entry, parseDependency );
+ } else {
+ doc = getJSDocFromToken( node, implementationNode ?? node );
+ }
+ if ( doc !== undefined ) {
+ return doc;
+ }
}
return doc;
}
diff --git a/packages/docgen/lib/get-jsdoc-from-token.js b/packages/docgen/lib/get-jsdoc-from-token.js
index 4b364c9a561b08..7bfe5141e55a0a 100644
--- a/packages/docgen/lib/get-jsdoc-from-token.js
+++ b/packages/docgen/lib/get-jsdoc-from-token.js
@@ -14,10 +14,14 @@ const getTypeAnnotation = require( './get-type-annotation' );
* a object representing the leading JSDoc comment of the token,
* if any.
*
- * @param {Object} token Espree token.
+ * @param {Object} token Espree token to extract the leading JSDoc comment from.
+ * @param {Object} [typeAnnotationToken] Espree token to use for type inference. Defaults to `token`.
+ * Pass the function implementation node when the JSDoc lives on
+ * an overload signature so that inferred types reflect the
+ * implementation's parameter/return types.
* @return {Object} Object representing the JSDoc comment.
*/
-module.exports = ( token ) => {
+module.exports = ( token, typeAnnotationToken = token ) => {
let jsdoc;
const comments = getLeadingComments( token );
if ( comments && /^\*\r?\n/.test( comments ) ) {
@@ -44,7 +48,7 @@ module.exports = ( token ) => {
return {
...tag,
- type: getTypeAnnotation( tag, token, index ),
+ type: getTypeAnnotation( tag, typeAnnotationToken, index ),
description:
tag.description === '\n'
? tag.description.trim()
@@ -55,7 +59,7 @@ module.exports = ( token ) => {
if ( jsdoc.tags.length === 0 ) {
const potentialTypeAnnotation = getTypeAnnotation(
{ tag: 'type' },
- token,
+ typeAnnotationToken,
0
);
if ( potentialTypeAnnotation ) {
diff --git a/packages/docgen/test/get-intermediate-representation.js b/packages/docgen/test/get-intermediate-representation.js
index e61f3101ad8438..109bc7ecf01815 100644
--- a/packages/docgen/test/get-intermediate-representation.js
+++ b/packages/docgen/test/get-intermediate-representation.js
@@ -662,6 +662,64 @@ describe( 'Intermediate Representation', () => {
} );
} );
+ describe( 'TypeScript function overloads', () => {
+ it( 'extracts description from first overload signature and infers types from the implementation', () =>
+ expect(
+ parse( `
+ /**
+ * Registers a new block.
+ * @param blockNameOrMetadata Block type name or its metadata.
+ * @param settings Block settings.
+ * @return The block, if registered; otherwise undefined.
+ */
+ export function registerBlockType( blockNameOrMetadata: object, settings?: object ): object | undefined;
+ export function registerBlockType( blockNameOrMetadata: string, settings: object ): object | undefined;
+ export function registerBlockType( blockNameOrMetadata: string | object, settings?: object ): object | undefined {
+ return undefined;
+ }
+ ` )
+ ).toEqual( [
+ expect.objectContaining( {
+ description: 'Registers a new block.',
+ name: 'registerBlockType',
+ tags: expect.arrayContaining( [
+ expect.objectContaining( {
+ tag: 'param',
+ name: 'blockNameOrMetadata',
+ type: 'string | object',
+ } ),
+ expect.objectContaining( {
+ tag: 'return',
+ type: 'object | undefined',
+ } ),
+ ] ),
+ } ),
+ ] ) );
+
+ it( 'extracts JSDoc from non-exported overload signatures exported via export { }', () =>
+ expect(
+ parse( `
+ /**
+ * My overloaded function.
+ * @param a The argument.
+ * @return The result.
+ */
+ function myDeclaration( a: string ): string;
+ function myDeclaration( a: number ): number;
+ function myDeclaration( a: string | number ): string | number {
+ return a;
+ }
+
+ export { myDeclaration };
+ ` )
+ ).toEqual( [
+ expect.objectContaining( {
+ description: 'My overloaded function.',
+ name: 'myDeclaration',
+ } ),
+ ] ) );
+ } );
+
describe( 'JSDoc in module dependency through import', () => {
describe( 'default export', () => {
it( 'default import', () =>