From 68306ab4737c6e1fc405a927d2a41ad8b1ff269d Mon Sep 17 00:00:00 2001 From: Dennis Snell Date: Thu, 31 Mar 2022 12:32:37 -0700 Subject: [PATCH 1/2] Core Data: Fixes necessary for converting to TypeScript In this commit we're cleaning up type issues in the core-data package that prevent us from telling TypeScript to run on the package and all of its existing code, even the JS files. After these changes we should be able to do so and start converting more modules to TypeScript with less friction. This patch follows a series of other smaller updates: - #39212 - #39214 - #39225 - #39476 - #39477 - #39479 - #39480 - #39525 - #39526 - #39655 - #39656 - #39659 It was built in order to support ongoing work to add types to the `getEntityRecord` family of functions in #39025. --- docs/reference-guides/data/data-core.md | 2 +- packages/core-data/README.md | 2 +- .../core-data/src/batch/default-processor.js | 1 + .../__experimental-fetch-link-suggestions.js | 56 +++++++++++-------- packages/core-data/src/reducer.js | 15 ++++- packages/core-data/src/selectors.js | 8 +-- .../core-data/src/utils/if-matching-action.js | 6 +- .../core-data/src/utils/replace-action.js | 6 +- packages/core-data/tsconfig.json | 20 +++++++ tsconfig.json | 1 + 10 files changed, 81 insertions(+), 36 deletions(-) create mode 100644 packages/core-data/tsconfig.json diff --git a/docs/reference-guides/data/data-core.md b/docs/reference-guides/data/data-core.md index aa493c7dcd997..ef10d8c4c3629 100644 --- a/docs/reference-guides/data/data-core.md +++ b/docs/reference-guides/data/data-core.md @@ -423,7 +423,7 @@ _Parameters_ - _state_ `Object`: State tree. - _kind_ `string`: Entity kind. - _name_ `string`: Entity name. -- _recordId_ `number`: Record ID. +- _recordId_ `number|string`: Record ID. _Returns_ diff --git a/packages/core-data/README.md b/packages/core-data/README.md index 2dc7df4a04d71..fd7f795b5d900 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -670,7 +670,7 @@ _Parameters_ - _state_ `Object`: State tree. - _kind_ `string`: Entity kind. - _name_ `string`: Entity name. -- _recordId_ `number`: Record ID. +- _recordId_ `number|string`: Record ID. _Returns_ diff --git a/packages/core-data/src/batch/default-processor.js b/packages/core-data/src/batch/default-processor.js index 34f38ff5c3d0d..d418955060565 100644 --- a/packages/core-data/src/batch/default-processor.js +++ b/packages/core-data/src/batch/default-processor.js @@ -36,6 +36,7 @@ export default async function defaultProcessor( requests ) { const results = []; + // @ts-ignore We would have crashed or never gotten to this point if we hadn't received the maxItems count. for ( const batchRequests of chunk( requests, maxItems ) ) { const batchResponse = await apiFetch( { path: '/batch/v1', diff --git a/packages/core-data/src/fetch/__experimental-fetch-link-suggestions.js b/packages/core-data/src/fetch/__experimental-fetch-link-suggestions.js index 09248d2102cda..bb1bf41d9e2cd 100644 --- a/packages/core-data/src/fetch/__experimental-fetch-link-suggestions.js +++ b/packages/core-data/src/fetch/__experimental-fetch-link-suggestions.js @@ -9,7 +9,7 @@ import { __ } from '@wordpress/i18n'; /** * Filters the search by type * - * @typedef { 'post' | 'term' | 'post-format' } WPLinkSearchType + * @typedef { 'attachment' | 'post' | 'term' | 'post-format' } WPLinkSearchType */ /** @@ -38,6 +38,17 @@ import { __ } from '@wordpress/i18n'; * @property {WPKind} [kind] Link kind of post-type or taxonomy */ +/** + * @typedef WPLinkSearchResultAugments + * + * @property {{kind: WPKind}} [meta] Contains kind information. + * @property {WPKind} [subtype] Optional subtype if it exists. + */ + +/** + * @typedef {WPLinkSearchResult & WPLinkSearchResultAugments} WPLinkSearchResultAugmented + */ + /** * @typedef WPEditorSettings * @@ -82,6 +93,7 @@ const fetchLinkSuggestions = async ( const { disablePostFormats = false } = settings; + /** @type {Promise[]} */ const queries = []; if ( ! type || type === 'post' ) { @@ -177,7 +189,8 @@ const fetchLinkSuggestions = async ( return Promise.all( queries ).then( ( results ) => { return results .reduce( - ( accumulator, current ) => accumulator.concat( current ), // Flatten list. + ( /** @type {WPLinkSearchResult[]} */ accumulator, current ) => + accumulator.concat( current ), // Flatten list. [] ) .filter( @@ -189,27 +202,24 @@ const fetchLinkSuggestions = async ( } ) .slice( 0, perPage ) - .map( - /** - * @param {{ id: number, meta?: object, url:string, title?:string, subtype?: string, type?: string }} result - */ - ( result ) => { - const isMedia = result.type === 'attachment'; - - return { - id: result.id, - url: isMedia ? result.source_url : result.url, - title: - decodeEntities( - isMedia - ? result.title.rendered - : result.title || '' - ) || __( '(no title)' ), - type: result.subtype || result.type, - kind: result?.meta?.kind, - }; - } - ); + .map( ( /** @type {WPLinkSearchResultAugmented} */ result ) => { + const isMedia = result.type === 'attachment'; + + return { + id: result.id, + // @ts-ignore fix when we make this a TS file + url: isMedia ? result.source_url : result.url, + title: + decodeEntities( + isMedia + ? // @ts-ignore fix when we make this a TS file + result.title.rendered + : result.title || '' + ) || __( '(no title)' ), + type: result.subtype || result.type, + kind: result?.meta?.kind, + }; + } ); } ); }; diff --git a/packages/core-data/src/reducer.js b/packages/core-data/src/reducer.js index b4034087bf696..f0f93b111234d 100644 --- a/packages/core-data/src/reducer.js +++ b/packages/core-data/src/reducer.js @@ -16,6 +16,8 @@ import { ifMatchingAction, replaceAction } from './utils'; import { reducer as queriedDataReducer } from './queried-data'; import { rootEntitiesConfig, DEFAULT_ENTITY_KEY } from './entities'; +/** @typedef {import('./types').AnyFunction} AnyFunction */ + /** * Reducer managing terms state. Keyed by taxonomy slug, the value is either * undefined (if no request has been made for given taxonomy), null (if a @@ -185,7 +187,7 @@ export function themeGlobalStyleVariations( state = {}, action ) { * * @param {Object} entityConfig Entity config. * - * @return {Function} Reducer. + * @return {AnyFunction} Reducer. */ function entity( entityConfig ) { return flowRight( [ @@ -406,7 +408,11 @@ export const entities = ( state = {}, action ) => { /** @typedef {Array & UndoStateMeta} UndoState */ -/** @type {UndoState} */ +/** + * @type {UndoState} + * + * @todo Given how we use this we might want to make a custom class for it. + */ const UNDO_INITIAL_STATE = Object.assign( [], { offset: 0 } ); /** @type {Object} */ @@ -416,7 +422,7 @@ let lastEditAction; * Reducer keeping track of entity edit undo history. * * @param {UndoState} state Current state. - * @param {Object} action Dispatched action. + * @param {Object} action Dispatched action. * * @return {UndoState} Updated state. */ @@ -455,6 +461,7 @@ export function undo( state = UNDO_INITIAL_STATE, action ) { let nextState; if ( isUndoOrRedo ) { + // @ts-ignore we might consider using Object.assign({}, state) nextState = [ ...state ]; nextState.offset = state.offset + ( action.meta.isUndo ? -1 : 1 ); @@ -494,6 +501,7 @@ export function undo( state = UNDO_INITIAL_STATE, action ) { ( key ) => ! action.transientEdits[ key ] ) ) { + // @ts-ignore we might consider using Object.assign({}, state) nextState = [ ...state ]; nextState.flattenedUndo = { ...state.flattenedUndo, @@ -505,6 +513,7 @@ export function undo( state = UNDO_INITIAL_STATE, action ) { // Clear potential redos, because this only supports linear history. nextState = + // @ts-ignore this needs additional cleanup, probably involving code-level changes nextState || state.slice( 0, state.offset || undefined ); nextState.offset = nextState.offset || 0; nextState.pop(); diff --git a/packages/core-data/src/selectors.js b/packages/core-data/src/selectors.js index 67cd6b1aa5087..279fd032d8581 100644 --- a/packages/core-data/src/selectors.js +++ b/packages/core-data/src/selectors.js @@ -501,10 +501,10 @@ export const getEntityRecordNonTransientEdits = createSelector( * Returns true if the specified entity record has edits, * and false otherwise. * - * @param {Object} state State tree. - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {number} recordId Record ID. + * @param {Object} state State tree. + * @param {string} kind Entity kind. + * @param {string} name Entity name. + * @param {number|string} recordId Record ID. * * @return {boolean} Whether the entity record has edits or not. */ diff --git a/packages/core-data/src/utils/if-matching-action.js b/packages/core-data/src/utils/if-matching-action.js index bbbe35800187b..022c4211a8a28 100644 --- a/packages/core-data/src/utils/if-matching-action.js +++ b/packages/core-data/src/utils/if-matching-action.js @@ -1,11 +1,13 @@ +/** @typedef {import('../types').AnyFunction} AnyFunction */ + /** * A higher-order reducer creator which invokes the original reducer only if * the dispatching action matches the given predicate, **OR** if state is * initializing (undefined). * - * @param {Function} isMatch Function predicate for allowing reducer call. + * @param {AnyFunction} isMatch Function predicate for allowing reducer call. * - * @return {Function} Higher-order reducer. + * @return {AnyFunction} Higher-order reducer. */ const ifMatchingAction = ( isMatch ) => ( reducer ) => ( state, action ) => { if ( state === undefined || isMatch( action ) ) { diff --git a/packages/core-data/src/utils/replace-action.js b/packages/core-data/src/utils/replace-action.js index 91cecb0e39151..92f22c22dd1bf 100644 --- a/packages/core-data/src/utils/replace-action.js +++ b/packages/core-data/src/utils/replace-action.js @@ -1,10 +1,12 @@ +/** @typedef {import('../types').AnyFunction} AnyFunction */ + /** * Higher-order reducer creator which substitutes the action object before * passing to the original reducer. * - * @param {Function} replacer Function mapping original action to replacement. + * @param {AnyFunction} replacer Function mapping original action to replacement. * - * @return {Function} Higher-order reducer. + * @return {AnyFunction} Higher-order reducer. */ const replaceAction = ( replacer ) => ( reducer ) => ( state, action ) => { return reducer( state, replacer( action ) ); diff --git a/packages/core-data/tsconfig.json b/packages/core-data/tsconfig.json new file mode 100644 index 0000000000000..35d05d8fa3b03 --- /dev/null +++ b/packages/core-data/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types", + "noUnusedParameters": false, + "noImplicitAny": false + }, + "references": [ + { "path": "../compose" }, + { "path": "../deprecated" }, + { "path": "../data" }, + { "path": "../element" }, + { "path": "../is-shallow-equal" }, + { "path": "../priority-queue" }, + { "path": "../redux-routine" }, + { "path": "../url" } + ], + "include": [ "src/**/*.js", "src/**/*.tsx", "src/**/*.ts" ] +} diff --git a/tsconfig.json b/tsconfig.json index 8a78ab8e69a83..8486f2dba941b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,6 +8,7 @@ { "path": "packages/block-editor" }, { "path": "packages/components" }, { "path": "packages/compose" }, + { "path": "packages/core-data" }, { "path": "packages/data" }, { "path": "packages/date" }, { "path": "packages/deprecated" }, From 643733a55360873faebc32ddcf3f6423be79d629 Mon Sep 17 00:00:00 2001 From: Dennis Snell Date: Thu, 31 Mar 2022 15:05:47 -0700 Subject: [PATCH 2/2] Don't actually enable TypeScript for the core-data package yet --- packages/core-data/tsconfig.json | 20 -------------------- tsconfig.json | 1 - 2 files changed, 21 deletions(-) delete mode 100644 packages/core-data/tsconfig.json diff --git a/packages/core-data/tsconfig.json b/packages/core-data/tsconfig.json deleted file mode 100644 index 35d05d8fa3b03..0000000000000 --- a/packages/core-data/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "rootDir": "src", - "declarationDir": "build-types", - "noUnusedParameters": false, - "noImplicitAny": false - }, - "references": [ - { "path": "../compose" }, - { "path": "../deprecated" }, - { "path": "../data" }, - { "path": "../element" }, - { "path": "../is-shallow-equal" }, - { "path": "../priority-queue" }, - { "path": "../redux-routine" }, - { "path": "../url" } - ], - "include": [ "src/**/*.js", "src/**/*.tsx", "src/**/*.ts" ] -} diff --git a/tsconfig.json b/tsconfig.json index 8486f2dba941b..8a78ab8e69a83 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,6 @@ { "path": "packages/block-editor" }, { "path": "packages/components" }, { "path": "packages/compose" }, - { "path": "packages/core-data" }, { "path": "packages/data" }, { "path": "packages/date" }, { "path": "packages/deprecated" },