From 7557055e44e74b8b05ace9d04f19614b540ad382 Mon Sep 17 00:00:00 2001 From: Manzoor Wani Date: Wed, 5 Aug 2026 10:33:55 +0530 Subject: [PATCH 1/2] Components: Use removeProperty to clear the drag cursor Setting `style.cursor = null` relied on WebIDL's LegacyNullToEmptyString coercion and needed a `@ts-expect-error`. `removeProperty( 'cursor' )` does the same thing in a type-compliant way. --- packages/components/src/input-control/utils.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/components/src/input-control/utils.ts b/packages/components/src/input-control/utils.ts index 71e477d978ea5f..b95e698b0cf54c 100644 --- a/packages/components/src/input-control/utils.ts +++ b/packages/components/src/input-control/utils.ts @@ -60,8 +60,7 @@ export function useDragCursor( if ( isDragging ) { document.documentElement.style.cursor = dragCursor; } else { - // @ts-expect-error `cursor` is typed as `string`, but `null` clears it. - document.documentElement.style.cursor = null; + document.documentElement.style.removeProperty( 'cursor' ); } }, [ isDragging, dragCursor ] ); From 9190b4d47084ffae3edbc350e2d76a5040e76a4b Mon Sep 17 00:00:00 2001 From: Manzoor Wani Date: Wed, 5 Aug 2026 10:41:16 +0530 Subject: [PATCH 2/2] Types: Replace remaining input-control, icon, dataviews and styles ts-expect-errors Follow-up to review feedback on #81148: type each of these sites so the suppression is unnecessary rather than describing why it was needed. - Icon: type the cloned element's props as the sizing props it forwards. - Properties section: key `isVisibleFlag` to the `View` flags it indexes. - Block supports: type the object form of `spacing.blockGap`. - Background: narrow `backgroundImage` with a type predicate. --- packages/blocks/src/types.ts | 11 +++++++++- packages/components/src/icon/index.tsx | 10 +++++++-- .../properties-section.tsx | 7 ++---- .../global-styles-engine/src/core/render.tsx | 7 ++++-- .../src/utils/background.ts | 22 +++++++++++++++++-- 5 files changed, 45 insertions(+), 12 deletions(-) diff --git a/packages/blocks/src/types.ts b/packages/blocks/src/types.ts index aad6663dbdb7cb..4d4f4633839220 100644 --- a/packages/blocks/src/types.ts +++ b/packages/blocks/src/types.ts @@ -840,8 +840,17 @@ export interface TypographyProps { export interface SpacingProps { /** * Enable block gap control. + * + * The object form declares the sides the control applies to, and the gap + * value to fall back to when neither the theme nor the user has set one. */ - blockGap: boolean | AxialDirection[]; + blockGap: + | boolean + | AxialDirection[] + | { + __experimentalDefault?: string; + sides?: AxialDirection[]; + }; /** * Enable margin control UI for all or specified element directions. diff --git a/packages/components/src/icon/index.tsx b/packages/components/src/icon/index.tsx index 73ee33d8258853..e54c95e249d69b 100644 --- a/packages/components/src/icon/index.tsx +++ b/packages/components/src/icon/index.tsx @@ -25,6 +25,13 @@ export type IconType = | ( ( props: { size?: number } ) => React.JSX.Element ) | React.JSX.Element; +/* The sizing props forwarded to an icon element that is not an `SVG` or a `Dashicon`. */ +type SizeProps = { + size?: number; + width?: number | string; + height?: number | string; +}; + type AdditionalProps< T > = T extends ComponentType< infer U > ? U : T extends DashiconIconKey @@ -103,9 +110,8 @@ function Icon( { return ; } - if ( isValidElement( icon ) ) { + if ( isValidElement< SizeProps >( icon ) ) { return cloneElement( icon, { - // @ts-expect-error `size` is forwarded but is not in the icon component overloads. size, width: size, height: size, diff --git a/packages/dataviews/src/components/dataviews-view-config/properties-section.tsx b/packages/dataviews/src/components/dataviews-view-config/properties-section.tsx index c74ec9f4e630eb..d6cc19eb6f7797 100644 --- a/packages/dataviews/src/components/dataviews-view-config/properties-section.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/properties-section.tsx @@ -80,7 +80,7 @@ export function PropertiesSection( { }, ].filter( ( { field } ) => isDefined( field ) ) as Array< { field: NormalizedField< any >; - isVisibleFlag: string; + isVisibleFlag: 'showTitle' | 'showMedia' | 'showDescription'; } >; const visibleFieldIds = view.fields ?? []; const visibleRegularFieldsCount = regularFields.filter( ( f ) => @@ -88,9 +88,7 @@ export function PropertiesSection( { ).length; const visibleLockedFields = lockedFields.filter( - ( { isVisibleFlag } ) => - // @ts-expect-error A string key cannot index `View`. - view[ isVisibleFlag ] ?? true + ( { isVisibleFlag } ) => view[ isVisibleFlag ] ?? true ); // If only one field (locked or regular) is visible, prevent it from being hidden @@ -112,7 +110,6 @@ export function PropertiesSection( { > { lockedFields.map( ( { field, isVisibleFlag } ) => { - // @ts-expect-error A string key cannot index `View`. const isVisible = view[ isVisibleFlag ] ?? true; const fieldToRender = isSingleVisibleLockedField && isVisible diff --git a/packages/global-styles-engine/src/core/render.tsx b/packages/global-styles-engine/src/core/render.tsx index e3f693418b02f1..8127000561206c 100644 --- a/packages/global-styles-engine/src/core/render.tsx +++ b/packages/global-styles-engine/src/core/render.tsx @@ -1921,9 +1921,12 @@ export const getBlockSelectors = ( const hasLayoutSupport = !! blockType?.supports?.layout || !! blockType?.supports?.__experimentalLayout; + const blockGapSupport = blockType?.supports?.spacing?.blockGap; const fallbackGapValue = - // @ts-expect-error `blockGap` support is typed as `boolean | AxialDirection[]`. - blockType?.supports?.spacing?.blockGap?.__experimentalDefault; + typeof blockGapSupport === 'object' && + ! Array.isArray( blockGapSupport ) + ? blockGapSupport.__experimentalDefault + : undefined; const blockStyleVariations = getBlockStyles( name ); const styleVariationSelectors: Record< string, string > = {}; diff --git a/packages/global-styles-engine/src/utils/background.ts b/packages/global-styles-engine/src/utils/background.ts index 41efe615b0b05d..fa7eb09c6c92fe 100644 --- a/packages/global-styles-engine/src/utils/background.ts +++ b/packages/global-styles-engine/src/utils/background.ts @@ -8,11 +8,29 @@ export const BACKGROUND_BLOCK_DEFAULT_VALUES = { backgroundPosition: '50% 50%', // used only when backgroundSize is 'contain'. }; +/** + * Whether a background image resolves to a URL, as opposed to a reference or an + * unresolved value. + * + * @param backgroundImage The background image value. + * + * @return Whether the value carries a URL. + */ +function hasImageUrl( + backgroundImage: BackgroundStyle[ 'backgroundImage' ] +): backgroundImage is { url: string } { + return ( + typeof backgroundImage === 'object' && + backgroundImage !== null && + 'url' in backgroundImage && + !! backgroundImage.url + ); +} + export function setBackgroundStyleDefaults( backgroundStyle: BackgroundStyle ) { if ( ! backgroundStyle || - // @ts-expect-error `backgroundImage` is a union whose other members have no `url`. - ! backgroundStyle?.backgroundImage?.url + ! hasImageUrl( backgroundStyle.backgroundImage ) ) { return; }