Skip to content

Conversation

@zzjiaxiang
Copy link
Contributor

@zzjiaxiang zzjiaxiang commented Dec 28, 2025

React 开发版本升级到 v19.
resolutionsyarn 特有的. 我们使用了 pnpm 似乎可以移除了.

Summary by CodeRabbit

发布说明

  • 升级依赖

    • React 和 React-DOM 升级至 19.x 版本
    • react-markdown 升级至 10.1.0 版本
  • 重构

    • 优化类型系统以提升类型安全性
    • 规范化内部引用初始化流程
  • 文档

    • 更新组件 API 文档以反映类型变更

✏️ Tip: You can customize this high-level summary in your review settings.

@dosubot dosubot bot added the size:S This PR changes 10-29 lines, ignoring generated files. label Dec 28, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 28, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

本PR升级React和相关依赖至19版本,统一refs初始化方式(添加explicit undefined),将ref类型从MutableRefObject改为RefObject,将JSX.Element统一改为React.ReactElement,并调整相应的类型断言。

Changes

Cohort / File(s) 变更总结
Package 升级
package.json
React、ReactDOM及相关类型依赖从^18升至^19;移除transitive typings的resolutions块;react-markdown升至^10.1.0
Demo refs初始化标准化
demos/descriptions/*, demos/form/*, demos/layout/*, demos/list/*, demos/table/*
统一useRef初始化:从useRef<Type>()改为useRef<Type>(undefined),使initial value明确;部分demo添加显式类型注解
Form组件ref类型改造
src/form/BaseForm/BaseForm.tsx, src/form/components/List/index.tsx, src/form/layouts/StepsForm/index.tsx, src/form/layouts/ModalForm/index.tsx, src/form/layouts/DrawerForm/index.tsx
actionRef、formRef从MutableRefObject改为RefObject;简化ref赋值逻辑;formRef初始化加explicit undefined
Field和Form通用类型统一
src/field/AllProField.tsx, src/field/PureProField.tsx, src/field/components/Image/index.tsx, src/form/BaseForm/Submitter/index.tsx
JSX.Element替换为React.ReactElement;移除ProFieldFC类型cast;简化forwardRef公共导出;调整render回调参数类型
Table相关ref与类型重构
src/table/Store/Provide.tsx, src/table/Table.tsx, src/table/components/EditableTable/index.tsx, src/table/components/Form/FormRender.tsx, src/table/components/ToolBar/index.tsx, src/table/utils/index.ts, src/table/useFetchData.tsx
actionRef、formRef等refs从MutableRefObject改RefObject;updateRef初始化加explicit undefined;updateRef类型参数优化
Layout组件属性类型调整
src/layout/ProLayout.tsx, src/layout/components/FooterToolbar/index.tsx
actionRef从MutableRefObject改RefObject;logo、trigger、submitter从JSX.Element改React.ReactElement
List组件ref与render类型
src/list/Item.tsx, src/list/ListView.tsx, src/list/index.tsx
actionRef改RefObject;expandIcon、defaultDom、renderItem参数类型从JSX.Element改React.ReactElement
utility hooks ref类型统一
src/utils/hooks/useReactiveRef/index.ts, src/utils/hooks/useRefCallback/index.ts, src/utils/hooks/usePrevious/index.ts, src/utils/hooks/useDeepCompareEffect/index.ts, src/utils/hooks/useDebounceFn/index.ts
所有返回类型从MutableRefObject改RefObject;timer/ref初始化加undefined;移除MutableRefObject import
公共context与工具类型
src/utils/components/DropdownFooter/index.tsx, src/utils/components/FilterDropdown/index.tsx, src/utils/components/InlineErrorFormItem/index.tsx, src/utils/typing.ts, src/provider/index.tsx
JSX.Element统一改React.ReactElement;footer/render返回类型调整;formRef改RefObject
Schema与Form类型声明
src/form/components/SchemaForm/typing.ts
action、formRef从MutableRefObject改RefObject
doc API文档更新
site/components/descriptions/index.*.md, site/components/layout/index.*.md, site/components/list/index.*.md, site/components/schema-form/index.*.md
公开API表中actionRef、action、formRef类型从MutableRefObject改为React.Ref
Test文件ref初始化更新
tests/descriptions/*, tests/field/*, tests/form/*, tests/table/*
对齐demo/src的ref初始化标准化;useRef替代createRef;类型参数显式化
Minor文档格式修复
site/components/table/index.*.md
修正markdown代码块分隔符缩进

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

说明:PR涉及广泛的文件(100+),但改动模式高度同质化,主要为机械化的类型转换和ref初始化标准化。虽然总行数较多,但每个改动的复杂度低,且遵循一致的模式。需要关注的重点是确认ref类型从MutableRefObject改为RefObject的语义变化(从可变改为只读)是否符合意图,以及React 19兼容性。

Possibly related PRs

Suggested labels

table, size:XXL, refactor, types

Poem

🐰 Refs的模式换一换,
不可变变成只读啦!
ReactElement更规范,
类型安全真靠谱,
React十九来报道!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 拉取请求的标题「chore: upgrade to React 19」准确反映了主要变更:将React从18版本升级到19版本。标题简洁明了,涵盖了此次PR的核心目标。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

🧹 Recent nitpick comments
src/field/components/Select/index.tsx (1)

401-401: React 19 兼容性更改正确,但建议添加显式类型注解。

useRef(undefined) 的更改符合 React 19 的要求。但与第 403 行的 keyWordsRef 相比,inputRef 缺少显式类型注解。当前写法会被推断为 MutableRefObject<undefined>,这可能导致后续将 ref 传递给 LightSelectSearchSelect 时产生类型不匹配的问题。

根据 coding guidelines,Component ref types 应该显式定义。

💡 建议添加显式类型
-  const inputRef = useRef(undefined);
+  const inputRef = useRef<React.ElementRef<typeof SearchSelect> | undefined>(undefined);

或者如果 LightSelectSearchSelect 有共同的 ref 类型,可以定义一个统一的类型。

demos/form/FieldSet/captCha.tsx (1)

66-69: 建议使用 Tailwind 类替代内联样式。

根据编码规范,应使用 Tailwind 类进行样式设置。

♻️ 建议的修改
 export default () => (
-  <div style={{ padding: 24 }}>
+  <div className="p-6">
     <Demo />
   </div>
 );
site/components/layout/index.en-US.md (1)

84-84: 为 React 19 类型变更添加版本信息。

根据编码规范,文档中的新属性应声明可用的版本号。由于 actionRef 的类型从 MutableRefObject 更改为 React.Ref,这是 React 19 升级的一部分,建议在文档中标注此更改适用的版本。

📝 建议的文档改进

在 API 表格中为 actionRef 添加版本标注,例如:

-| actionRef                  | Common operations of layout, such as reloading menu                                                                                                                         | `React.Ref<{reload: () => void} \| undefined>`                                                                                           | -                                        |
+| actionRef                  | Common operations of layout, such as reloading menu <Badge type="info">React 19+</Badge>                                                                                    | `React.Ref<{reload: () => void} \| undefined>`                                                                                           | -                                        |

或在描述中说明:

-| actionRef                  | Common operations of layout, such as reloading menu                                                                                                                         | `React.Ref<{reload: () => void} \| undefined>`                                                                                           | -                                        |
+| actionRef                  | Common operations of layout, such as reloading menu (type updated for React 19)                                                                                             | `React.Ref<{reload: () => void} \| undefined>`                                                                                           | -                                        |

基于编码规范要求,文档应声明新属性的可用版本号。

site/components/list/index.en-US.md (1)

69-69: 为 React 19 类型变更添加版本信息。

与 ProLayout 类似,actionRef 的类型从 MutableRefObject 更改为 React.Ref 是 React 19 升级的一部分。根据编码规范,应在文档中标注此更改适用的版本。

📝 建议的文档改进
-| actionRef        | Table action reference for custom triggering                                                                                                                                                                                           | `React.Ref<ActionType>`                   | -             |
+| actionRef        | Table action reference for custom triggering (type updated for React 19)                                                                                                                                                               | `React.Ref<ActionType>`                   | -             |

基于编码规范要求,文档应声明新属性的可用版本号。

site/components/descriptions/index.en-US.md (1)

112-112: 类型改进合理,建议添加版本信息。

actionRef 的类型从 MutableRefObject<ActionType> 更改为 React.Ref<ActionType> 是正确的改进。React.Ref<T> 是一个联合类型(RefCallback<T> | RefObject<T> | null),可以同时接受 ref 对象和 ref 回调函数,更加灵活且符合 React 19 的 ref 作为常规 prop 的设计。

建议在文档中标注此更改适用于 React 19。

📝 建议的文档改进
-| actionRef      | Operation reference                                                                                                                        | `React.Ref<ActionType>`                        | -             |
+| actionRef      | Operation reference (type updated for React 19)                                                                                            | `React.Ref<ActionType>`                        | -             |

基于编码规范要求,文档应声明新属性的可用版本号。

site/components/descriptions/index.md (1)

112-112: 类型改进合理,建议添加版本信息。

actionRef 的类型从 MutableRefObject<ActionType> 更改为 React.Ref<ActionType> 符合 React 19 的新特性(ref 作为常规 prop)。React.Ref<T> 类型更加灵活,可以接受 ref 对象和 ref 回调函数。

建议在文档中标注此更改适用的版本号。

📝 建议的文档改进
-| actionRef      | 操作引用                                                                                          | `React.Ref<ActionType>`                  | -            |
+| actionRef      | 操作引用(类型已针对 React 19 更新)                                                               | `React.Ref<ActionType>`                  | -            |

基于编码规范要求,文档应声明新属性的可用版本号。

site/components/schema-form/index.md (1)

25-26: 为 React 19 类型变更添加版本信息。

actionformRef 的类型从 MutableRefObject 更改为 React.Ref 是 React 19 升级的一部分。根据编码规范,应在文档中标注这些更改适用的版本。

📝 建议的文档改进
-| `action`       | `React.Ref<ProCoreActionType \| undefined>`                                               | 用于操作表单的 action,支持 reload 等操作                                                                                                                                                                                                                                              |
-| `formRef`      | `React.Ref<ProFormInstance \| undefined>`                                                 | 获取 form 实例,支持 antd form 的所有方法                                                                                                                                                                                                                                              |
+| `action`       | `React.Ref<ProCoreActionType \| undefined>`                                               | 用于操作表单的 action,支持 reload 等操作(类型已针对 React 19 更新)                                                                                                                                                                                                                    |
+| `formRef`      | `React.Ref<ProFormInstance \| undefined>`                                                 | 获取 form 实例,支持 antd form 的所有方法(类型已针对 React 19 更新)                                                                                                                                                                                                                    |

基于编码规范要求,文档应声明新属性的可用版本号。


📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 95e60c0 and 54f5ade.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (34)
  • demos/form/FieldSet/captCha.tsx
  • demos/form/StepsForm/steps-from.tsx
  • package.json
  • site/components/descriptions/index.en-US.md
  • site/components/descriptions/index.md
  • site/components/layout/index.en-US.md
  • site/components/layout/index.md
  • site/components/list/index.en-US.md
  • site/components/list/index.md
  • site/components/schema-form/index.en-US.md
  • site/components/schema-form/index.md
  • src/field/components/Cascader/index.tsx
  • src/field/components/Radio/index.tsx
  • src/field/components/Select/index.tsx
  • src/form/BaseForm/BaseForm.tsx
  • src/form/BaseForm/LightWrapper/index.tsx
  • src/form/components/FormItem/Group/index.tsx
  • src/form/layouts/LightFilter/index.tsx
  • src/form/layouts/QueryFilter/index.tsx
  • src/form/layouts/StepsForm/StepForm.tsx
  • src/layout/ProLayout.tsx
  • src/layout/components/GlobalHeader/ActionsContent.tsx
  • src/layout/components/SiderMenu/BaseMenu.tsx
  • src/table/Store/Provide.tsx
  • src/table/Table.tsx
  • src/table/components/Form/index.tsx
  • src/table/components/ListToolBar/index.tsx
  • src/table/components/ToolBar/index.tsx
  • src/table/useFetchData.tsx
  • src/utils/components/FilterDropdown/index.tsx
  • src/utils/components/InlineErrorFormItem/index.tsx
  • src/utils/useEditableArray/index.tsx
  • tests/form/base.test.tsx
  • tests/form/modalForm.test.tsx
🚧 Files skipped from review as they are similar to previous changes (22)
  • src/table/Store/Provide.tsx
  • demos/form/StepsForm/steps-from.tsx
  • site/components/list/index.md
  • site/components/layout/index.md
  • src/form/components/FormItem/Group/index.tsx
  • src/table/Table.tsx
  • tests/form/modalForm.test.tsx
  • src/layout/components/GlobalHeader/ActionsContent.tsx
  • src/layout/ProLayout.tsx
  • src/form/BaseForm/LightWrapper/index.tsx
  • src/field/components/Cascader/index.tsx
  • src/table/components/ListToolBar/index.tsx
  • src/table/components/Form/index.tsx
  • src/layout/components/SiderMenu/BaseMenu.tsx
  • package.json
  • src/form/layouts/StepsForm/StepForm.tsx
  • src/table/components/ToolBar/index.tsx
  • tests/form/base.test.tsx
  • src/utils/useEditableArray/index.tsx
  • src/form/BaseForm/BaseForm.tsx
  • src/table/useFetchData.tsx
  • src/form/layouts/QueryFilter/index.tsx
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/react.mdc)

**/*.{tsx,jsx}: Use early returns whenever possible to make the code more readable.
Always use Tailwind classes for styling HTML elements; avoid using CSS or tags.
Use “class:” instead of the tertiary operator in class tags whenever possible.
Use descriptive variable and function/const names. Also, event functions should be named with a “handle” prefix, like “handleClick” for onClick and “handleKeyDown” for onKeyDown.
Implement accessibility features on elements. For example, a tag should have a tabindex=“0”, aria-label, on:click, and on:keydown, and similar attributes.
Use consts instead of functions, for example, “const toggle = () =>”. Also, define a type if possible.

Files:

  • src/utils/components/FilterDropdown/index.tsx
  • src/utils/components/InlineErrorFormItem/index.tsx
  • src/field/components/Radio/index.tsx
  • demos/form/FieldSet/captCha.tsx
  • src/field/components/Select/index.tsx
  • src/form/layouts/LightFilter/index.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/AGENTS.md)

**/*.{ts,tsx}: Use TypeScript and React for development
Use early returns to improve code readability
Use camelCase for property names
Props naming: Use default + PropName for initialization properties
Props naming: Use forceRender for forced rendering
Props naming: Use force + SubComponentName + Render for sub-component forced rendering
Props naming: Use SubComponentName + Render for sub-component rendering
Props naming: Use dataSource for data sources
Props naming: Use open instead of visible for panel opening state
Props naming: Use show + PropName for display-related properties
Props naming: Use PropName + able for functional properties
Props naming: Use disabled for disabled state
Props naming: Use extra for additional content
Props naming: Use icon for icons
Props naming: Use trigger for triggers
Props naming: Use className for class names
Event naming: Use on + EventName for triggering events
Event naming: Use on + SubComponentName + EventName for sub-component events
Event naming: Use before + EventName for pre-action events
Event naming: Use after + EventName for post-action events
Event naming: Use on + EventName + Complete for continuous action completion
All components and functions must provide accurate type definitions
Avoid using any type, define types as precisely as possible
Use interface rather than type alias for defining object structures
Strictly follow TypeScript type design principles to ensure type safety
Ensure compilation without any type errors or warnings
Component props should be defined using interface for extensibility
Component props interface naming should follow ComponentNameProps convention
Define specialized interfaces for component state, such as ComponentNameState
Complex data structures should be split into multiple interface definitions
All callback function types should explicitly define parameters and return values
Appropriately use generics to enhance t...

Files:

  • src/utils/components/FilterDropdown/index.tsx
  • src/utils/components/InlineErrorFormItem/index.tsx
  • src/field/components/Radio/index.tsx
  • demos/form/FieldSet/captCha.tsx
  • src/field/components/Select/index.tsx
  • src/form/layouts/LightFilter/index.tsx
**/*index.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/AGENTS.md)

Export all public interface types for user convenience

Files:

  • src/utils/components/FilterDropdown/index.tsx
  • src/utils/components/InlineErrorFormItem/index.tsx
  • src/field/components/Radio/index.tsx
  • src/field/components/Select/index.tsx
  • src/form/layouts/LightFilter/index.tsx
**/*.{tsx,ts}

📄 CodeRabbit inference engine (.cursor/rules/AGENTS.md)

All components must support dark mode

Files:

  • src/utils/components/FilterDropdown/index.tsx
  • src/utils/components/InlineErrorFormItem/index.tsx
  • src/field/components/Radio/index.tsx
  • demos/form/FieldSet/captCha.tsx
  • src/field/components/Select/index.tsx
  • src/form/layouts/LightFilter/index.tsx
**/*.md

📄 CodeRabbit inference engine (.cursor/rules/AGENTS.md)

**/*.md: Provide both Chinese and English versions of documentation
Declare available version numbers for new properties
Property naming in documentation should follow antd API naming rules

Files:

  • site/components/list/index.en-US.md
  • site/components/layout/index.en-US.md
  • site/components/schema-form/index.en-US.md
  • site/components/schema-form/index.md
  • site/components/descriptions/index.en-US.md
  • site/components/descriptions/index.md
🧠 Learnings (10)
📓 Common learnings
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-12-26T06:32:24.230Z
Learning: Support React 16 ~ 19 compatibility
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-12-26T06:32:24.230Z
Learning: Applies to **/*.{tsx} : Component ref types should be explicitly defined using `React.ForwardRefRenderFunction`
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-12-26T06:32:24.230Z
Learning: Applies to **/*.{tsx} : Components should provide a `ref` attribute with structure including `nativeElement`, `focus`, and other functions
📚 Learning: 2025-12-26T06:32:24.230Z
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-12-26T06:32:24.230Z
Learning: Applies to **/*.{tsx} : Component ref types should be explicitly defined using `React.ForwardRefRenderFunction`

Applied to files:

  • src/utils/components/FilterDropdown/index.tsx
  • src/utils/components/InlineErrorFormItem/index.tsx
  • src/field/components/Radio/index.tsx
  • site/components/layout/index.en-US.md
  • site/components/schema-form/index.en-US.md
  • site/components/schema-form/index.md
  • demos/form/FieldSet/captCha.tsx
  • site/components/descriptions/index.en-US.md
  • src/field/components/Select/index.tsx
  • site/components/descriptions/index.md
  • src/form/layouts/LightFilter/index.tsx
📚 Learning: 2025-12-26T06:32:24.230Z
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-12-26T06:32:24.230Z
Learning: Applies to **/*.{ts,tsx} : Props naming: Use `dataSource` for data sources

Applied to files:

  • site/components/list/index.en-US.md
📚 Learning: 2025-12-26T06:32:24.230Z
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-12-26T06:32:24.230Z
Learning: Applies to **/*.{tsx} : Components should provide a `ref` attribute with structure including `nativeElement`, `focus`, and other functions

Applied to files:

  • src/field/components/Radio/index.tsx
  • site/components/schema-form/index.en-US.md
  • site/components/schema-form/index.md
  • demos/form/FieldSet/captCha.tsx
  • site/components/descriptions/index.en-US.md
  • src/field/components/Select/index.tsx
  • src/form/layouts/LightFilter/index.tsx
📚 Learning: 2025-12-26T06:32:24.230Z
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-12-26T06:32:24.230Z
Learning: Update related documentation for PR changes

Applied to files:

  • site/components/layout/index.en-US.md
  • site/components/schema-form/index.md
  • site/components/descriptions/index.en-US.md
  • site/components/descriptions/index.md
📚 Learning: 2025-12-26T06:32:24.230Z
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-12-26T06:32:24.230Z
Learning: Applies to **/*.md : Property naming in documentation should follow antd API naming rules

Applied to files:

  • site/components/layout/index.en-US.md
  • site/components/schema-form/index.en-US.md
  • site/components/descriptions/index.en-US.md
📚 Learning: 2025-08-01T09:28:05.125Z
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T09:28:05.125Z
Learning: Applies to **/*.{tsx,jsx} : Use consts instead of functions, for example, “const toggle = () =>”. Also, define a type if possible.

Applied to files:

  • demos/form/FieldSet/captCha.tsx
  • site/components/descriptions/index.en-US.md
📚 Learning: 2025-12-26T06:32:24.230Z
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-12-26T06:32:24.230Z
Learning: Applies to **/*.{ts,tsx} : All components and functions must provide accurate type definitions

Applied to files:

  • site/components/descriptions/index.en-US.md
📚 Learning: 2025-08-01T09:28:05.125Z
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T09:28:05.125Z
Learning: Applies to **/*.{tsx,jsx} : Use descriptive variable and function/const names. Also, event functions should be named with a “handle” prefix, like “handleClick” for onClick and “handleKeyDown” for onKeyDown.

Applied to files:

  • site/components/descriptions/index.en-US.md
📚 Learning: 2025-12-26T06:32:24.230Z
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-12-26T06:32:24.230Z
Learning: Applies to **/*.{tsx} : Use complete names rather than abbreviations in Antd naming

Applied to files:

  • site/components/descriptions/index.en-US.md
🧬 Code graph analysis (2)
demos/form/FieldSet/captCha.tsx (1)
src/form/components/Captcha/index.tsx (1)
  • CaptFieldRef (31-40)
src/form/layouts/LightFilter/index.tsx (1)
src/form/BaseForm/BaseForm.tsx (1)
  • ProFormInstance (57-57)
🔇 Additional comments (10)
src/utils/components/FilterDropdown/index.tsx (1)

10-15: 类型更新符合 React 19 规范,LGTM!

将返回类型从 JSX.Element 改为 React.ReactElement 是正确的做法。React 19 移除了全局 JSX 命名空间,推荐使用 React.ReactElementReact.JSX.Element

此更改与 DropdownFooter 中的 LightFilterFooterRender 类型保持一致,确保了整个代码库的类型统一性。根据提供的库文档,这是 React 19 的标准迁移模式。

src/form/layouts/LightFilter/index.tsx (1)

295-295: LGTM! React 19 兼容性更新正确。

根据 React 19 的 TypeScript 变更,useRef 现在需要显式传入初始值参数。将 useRef<ProFormInstance>() 改为 useRef<ProFormInstance>(undefined) 是正确的迁移方式。

代码中对 formRef.current 的所有访问(第 329、330、352 行)都已正确使用可选链(?.),能够安全处理 undefined 的情况。

src/field/components/Radio/index.tsx (2)

1-1: LGTM!

正确导入了 GetRef 类型,用于后续对 Radio.Group 的 ref 进行类型推导。


28-28: LGTM!

使用 GetRef<typeof Radio.Group> 正确提取了组件的 ref 类型,并以 null 作为初始值,符合 React 19 对组件 ref 的初始化规范。这比之前未类型化的 useRef() 更具类型安全性。

src/utils/components/InlineErrorFormItem/index.tsx (3)

6-8: LGTM!

正确添加了 ReactElement 类型导入,符合 React 19 移除全局 JSX 命名空间的变更。该类型在 React 16+ 中都可用,保持了向后兼容性。


30-36: LGTM!

inputerrorListextra 的类型从 JSX.Element 改为 ReactElement 是 React 19 的正确迁移方式。根据 learnings,项目需要支持 React 16 ~ 19 兼容性,ReactElement 类型在这些版本中都可用,此变更是安全的。


118-136: LGTM!

_internalItemRenderdoms 参数的类型更新与上面 InlineErrorFormItemPopover 组件的 props 类型保持一致,确保了类型定义的统一性。

demos/form/FieldSet/captCha.tsx (2)

1-1: 类型导入正确,符合 React 19 升级要求。

正确导入了 CaptFieldRef 类型,与 src/form/components/Captcha/index.tsx 中定义的类型一致,包含 startTimingendTiming 方法。


15-15: Ref 类型定义改进良好,已解决之前的类型问题。

useRef<CaptFieldRef>(undefined) 的写法:

  1. 符合 React 19 要求(useRef 必须提供显式参数)
  2. 提供了明确的泛型类型,消除了之前需要 @ts-ignore 的问题
  3. ProFormCaptchafieldRef prop 类型匹配

这个改动很好地解决了之前 review 中提到的类型问题。

site/components/schema-form/index.en-US.md (1)

25-26: 中英文文档类型定义一致性已确认

已验证 site/components/schema-form/index.md(中文版)与 index.en-US.md(英文版)的类型定义保持一致。actionformRef 属性在两个版本中的类型均为:

  • action: React.Ref<ProCoreActionType \| undefined>
  • formRef: React.Ref<ProFormInstance \| undefined>

文档符合编码指南要求,中英文两个版本均已同步更新。

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @zzjiaxiang, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

此拉取请求旨在将项目核心的 React 库升级到最新的 v19 版本。这包括更新 React 和 ReactDOM 的主要依赖项及其相应的类型定义,同时清理了不再需要的 yarn 特有配置,以确保项目依赖的现代化和一致性。

Highlights

  • React 版本升级: 将核心的 reactreact-dom 依赖项升级到最新的 ^19.2.3 版本。
  • 类型定义更新: 将 reactreact-dom 的类型定义 @types/react@types/react-dom 升级到与 React 19 兼容的版本。
  • 移除冗余配置: 从 package.json 中移除了 resolutions 字段,因为该项目使用 pnpm 而非 yarn,此字段不再需要。

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@socket-security
Copy link

socket-security bot commented Dec 28, 2025

@dosubot dosubot bot added the dependencies Pull requests that update a dependency file label Dec 28, 2025
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

感谢您升级 React 到 v19。这是一个重要的更新,移除 resolutions 字段也是正确的,因为 pnpm 使用 overrides

不过,本次升级似乎还不完整,有几个关键点需要注意:

  1. 破坏性变更:React 19 引入了一些破坏性变更。例如,React.FC 不再隐式包含 children 属性。您的代码库中有多处使用了 React.FC(如 ProLayout.tsx),这可能会导致 TypeScript 编译错误。建议在合并前,对整个代码库进行检查和适配,可以考虑使用官方的 codemods 来辅助升级。

  2. peerDependencies 更新:作为组件库,package.json 中的 peerDependencies 需要更新以反映对 React 19 的支持。这对于库的使用者至关重要,可以避免版本不兼容的问题。

在合并之前,请确保:

  • 更新 peerDependencies 来匹配新的 React 版本。
  • 修复所有因 React 19 破坏性变更而导致的代码问题。
  • 所有测试用例都能通过,并且 tsc 编译没有错误。

Comment on lines +173 to +174
"react": "^19.2.3",
"react-dom": "^19.2.3",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

升级到 React 19 后,建议同步更新 peerDependencies,以明确此库所支持的 React 版本。这对于库的使用者来说非常重要,可以避免版本兼容性问题。

如果库同时支持 React 18 和 19,peerDependencies 可以设置为:

"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0"

如果仅支持 React 19,则应设置为:

"react": "^19.0.0",
"react-dom": "^19.0.0"

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
package.json (1)

147-147: 必须升级 eslint-plugin-react-hooks 到 v6+。

React 19 要求 eslint-plugin-react-hooks 使用 v6 或更高版本以支持新的 Hook 语义。当前版本 ^4.6.2 与 React 19 不兼容,可能导致 Hook 使用问题无法被正确检测。

🔎 修复建议
-    "eslint-plugin-react-hooks": "^4.6.2",
+    "eslint-plugin-react-hooks": "^6.0.0",

根据 React 19.2 文档:React 19.2 requires eslint-plugin-react-hooks v6+ for new hook semantics.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8858ab2 and 1814a96.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (1)
  • package.json
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-12-26T06:32:24.230Z
Learning: Support React 16 ~ 19 compatibility
📚 Learning: 2025-12-26T06:32:24.230Z
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-12-26T06:32:24.230Z
Learning: Support React 16 ~ 19 compatibility

Applied to files:

  • package.json
📚 Learning: 2025-12-26T06:32:24.230Z
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-12-26T06:32:24.230Z
Learning: Applies to **/*.test.{ts,tsx} : Use Jest and React Testing Library for unit tests

Applied to files:

  • package.json
📚 Learning: 2025-12-26T06:32:24.230Z
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-12-26T06:32:24.230Z
Learning: Support TypeScript 4.0+

Applied to files:

  • package.json
📚 Learning: 2025-12-26T06:32:24.230Z
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-12-26T06:32:24.230Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript and React for development

Applied to files:

  • package.json
📚 Learning: 2025-12-26T06:32:24.230Z
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-12-26T06:32:24.230Z
Learning: Applies to **/demo/**/*.tsx : Demo import order: React → Dependencies → Component Library → Custom Components → Types → Styles

Applied to files:

  • package.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build
  • GitHub Check: build (20.x, ubuntu-latest)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (3)
package.json (3)

200-201: 验证 peerDependencies 范围是否符合预期。

当前 peerDependencies 指定 "react": ">=18.0.0",这在技术上包含了 React 19。但根据项目学习记录,该项目应支持 React 16 ~ 19 兼容性

如果项目确实需要支持 React 16+,peerDependencies 应该更新为:

"react": ">=16.0.0",
"react-dom": ">=16.0.0"

如果项目已决定仅支持 React 18+,则当前配置正确,但需要更新相关文档和学习记录。

基于项目学习记录:Support React 16 ~ 19 compatibility

请确认预期的 React 版本支持范围,并相应更新 peerDependencies 或文档。


173-174: React 运行时已正确升级到 v19.2.3,代码库完全兼容。

扫描确认代码库中不存在 React 19 已移除的 API(propTypes、defaultProps、contextTypes、字符串 refs、createFactory 等)。ErrorBoundary 作为类组件实现是正确的,符合 React 规范。无需运行迁移 codemods,升级可直接使用。


119-120: eslint-plugin-react-hooks 版本过低,useRef 调用需要修复以支持 React 19。

@types/react 和 @types/react-dom 类型定义已正确更新到 React 19。但存在两个需要立即修复的问题:

  1. eslint-plugin-react-hooks 版本不兼容:当前版本 ^4.6.2 不支持 React 19 新增的 hooks(useActionState、useFormStatus、useOptimistic 等)。需升级至 ^6.0.0+。

  2. useRef 调用存在 React 19 breaking change:发现 20+ 处 useRef() 不带初始值的调用需要修复,包括 src/utils/hooks/useDeepCompareEffect/index.ts:10、src/field/components/Radio/index.tsx:28 等。React 19 要求 useRef 必须提供初始值参数(可为 undefined)。

@testing-library/react ^16.3.1 版本已兼容 React 19,peerDependencies 的 >=18.0.0 范围也支持 React 19。建议运行 TypeScript 编译验证是否存在类型错误。

⛔ Skipped due to learnings
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-12-26T06:32:24.230Z
Learning: Support React 16 ~ 19 compatibility
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-12-26T06:32:24.230Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript and React for development
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-12-26T06:32:24.230Z
Learning: Applies to **/*.test.{ts,tsx} : Use Jest and React Testing Library for unit tests
Learnt from: CR
Repo: ant-design/pro-components PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-12-26T06:32:24.230Z
Learning: Support TypeScript 4.0+

@zzjiaxiang zzjiaxiang marked this pull request as draft December 28, 2025 16:44
@zzjiaxiang
Copy link
Contributor Author

大部分都是类型的更改, 接受这个pr的话,我去修改类型错误.

@chenshuai2144 chenshuai2144 marked this pull request as ready for review December 30, 2025 09:32
Copilot AI review requested due to automatic review settings December 30, 2025 09:32
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR upgrades React and React DOM from v18 to v19 and removes the yarn-specific resolutions field from package.json since the project uses pnpm.

Key Changes:

  • React and React DOM upgraded from ^18.3.1/^18.3.27 to ^19.2.3/^19.2.7
  • Type definitions upgraded: @types/react from ^18.0.38 to ^19.2.7, @types/react-dom from ^18.0.11 to ^19.2.3
  • Removed resolutions field (yarn-specific configuration, unnecessary for pnpm)

Reviewed changes

Copilot reviewed 1 out of 2 changed files in this pull request and generated no comments.

File Description
package.json Updates React/React DOM to v19 and removes yarn-specific resolutions field
pnpm-lock.yaml Reflects updated dependency tree with React 19 and all peer dependencies

Review Summary:

The upgrade appears clean and consistent. All React-dependent packages in the lock file have been updated to use React 19 peer dependencies. The codebase uses React.FC extensively, which is compatible with React 19 (the deprecation only applies to React.FC.defaultProps, not the type itself). The defaultProps usage found in the code is for internal configuration objects, not the deprecated React component feature.

No critical issues identified. The removal of the resolutions field is appropriate for a pnpm-based project.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@zzjiaxiang zzjiaxiang marked this pull request as draft December 31, 2025 02:59
- Updated `react-markdown` version in `package.json`.
- Added `actionRef` using `useRef` in multiple demo components and tests for better reference handling.
- Updated documentation for `actionRef` in descriptions and form components.

This enhances the functionality and maintainability of the components.
@zzjiaxiang zzjiaxiang marked this pull request as ready for review January 4, 2026 05:47
@dosubot dosubot bot added size:M This PR changes 30-99 lines, ignoring generated files. and removed size:S This PR changes 10-29 lines, ignoring generated files. labels Jan 4, 2026
@zzjiaxiang
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Jan 4, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 19

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
demos/table/form.tsx (1)

83-169: 严重错误:return 语句后存在不可达代码

第 82 行的 return 语句之后(第 83-169 行)存在大量 JSX 代码,这些代码永远不会被执行。这会导致文档说明无法渲染,并且是明显的逻辑错误。

🔎 修复建议

将第 82 行的分号移除,并将整个 JSX 包裹在一个片段中:

  return (
+   <>
    <ProTable<TableListItem>
      columns={columns}
      request={() =>
        Promise.resolve({
          data: [
            {
              key: 1,
              name: `TradeCode ${1}`,
              createdAt: 1602572994055,
            },
          ],
          success: true,
        })
      }
      rowKey="key"
      pagination={{
        showSizeChanger: true,
      }}
      search={{
        collapsed,
        onCollapse: setCollapsed,
      }}
      formRef={ref}
      toolBarRender={() => [
        <Button
          key="set"
          onClick={() => {
            if (ref.current) {
              ref.current.setFieldsValue({
                name: 'test-xxx',
              });
            }
          }}
        >
          赋值
        </Button>,
        <Button
          key="submit"
          onClick={() => {
            if (ref.current) {
              ref.current.submit();
            }
          }}
        >
          提交
        </Button>,
      ]}
      options={false}
      dateFormatter="string"
      headerTitle="表单赋值"
    />
-  );

-  <div
+   <div
      style={{
        marginTop: '20px',
        padding: '20px',
        backgroundColor: '#f5f5f5',
        borderRadius: '6px',
      }}
    >
      {/* ...rest of the JSX... */}
-  </div>;
+  </div>
+  </>
+  );
demos/table/single.tsx (1)

243-353: 严重错误:return 语句后存在不可达代码

第 242 行的 return 语句之后(第 243-353 行)存在大量 JSX 代码,这些代码永远不会被执行。这会导致 ProTable 的属性说明文档无法渲染。

🔎 修复建议

将第 242 行的分号移除,并将整个 JSX 包裹在一个片段中:

  return (
+   <>
    <ProTable<GithubIssueItem>
      columns={columns}
      actionRef={actionRef}
      cardBordered
      request={async (params, sort, filter) => {
        console.log(sort, filter);
        await waitTime(2000);
        return request<{
          data: GithubIssueItem[];
        }>('https://proapi.azurewebsites.net/github/issues', {
          params,
        });
      }}
      editable={{
        type: 'multiple',
      }}
      columnsState={{
        persistenceKey: 'pro-table-singe-demos',
        persistenceType: 'localStorage',
        defaultValue: {
          option: { fixed: 'right', disable: true },
        },
        onChange(value) {
          console.log('value: ', value);
        },
      }}
      rowKey="id"
      search={{
        labelWidth: 'auto',
      }}
      options={{
        setting: {
          listsHeight: 400,
        },
      }}
      form={{
        // Since transform is configured, the submitted parameters are different from the defined ones, so they need to be transformed here
        syncToUrl: (values, type) => {
          if (type === 'get') {
            return {
              ...values,
              created_at: [values.startTime, values.endTime],
            };
          }
          return values;
        },
      }}
      pagination={{
        pageSize: 5,
        onChange: (page) => console.log(page),
      }}
      dateFormatter="string"
      headerTitle="Advanced Table"
      toolBarRender={() => [
        <Button
          key="button"
          icon={<PlusOutlined />}
          onClick={() => {
            actionRef.current?.reload();
          }}
          type="primary"
        >
          New
        </Button>,
        <Dropdown
          key="menu"
          menu={{
            items: [
              {
                label: '1st item',
                key: '1',
              },
              {
                label: '2nd item',
                key: '2',
              },
              {
                label: '3rd item',
                key: '3',
              },
            ],
          }}
        >
          <Button>
            <EllipsisOutlined />
          </Button>
        </Dropdown>,
      ]}
    />
-  );

-  <div
+   <div
      style={{
        marginTop: '20px',
        padding: '20px',
        backgroundColor: '#f5f5f5',
        borderRadius: '6px',
      }}
    >
      {/* ...rest of the JSX... */}
-  </div>;
+  </div>
+  </>
+  );
src/form/components/FormItem/index.tsx (1)

51-60: 静态分析提示:void 函数中存在返回值。

onChangeMemo 函数签名返回 void,但第 54 行有 return undefined;。这是一个轻微的类型不一致问题(非本 PR 引入)。

类型转换 (filedChildren?.props as any) 是 React 19 兼容性所需的正确做法。

🔎 建议修复
 const onChangeMemo = useRefFunction(function (...restParams: any[]): void {
   onChange?.(...restParams);
   if (isProFormComponent) return;
-  if (isValidElementForFiledChildren) return undefined;
+  if (isValidElementForFiledChildren) return;
   (filedChildren?.props as any)?.onChange?.(...restParams);

   (filedChildren?.props as Record<string, any>)?.fieldProps?.onChange?.(
     ...restParams,
   );
 });
🧹 Nitpick comments (21)
src/utils/hooks/useDebounceFn/index.ts (1)

14-14: 符合 React 19 要求,但建议改进类型安全性。

显式传入 undefined 参数符合 React 19 的 useRef 要求,更改本身正确。但是:

  1. 类型改进:当前使用 any 类型,建议改为更精确的类型。根据编码规范,应避免使用 any,尽可能精确定义类型。
  2. 值的一致性:初始化为 undefined,但在 line 19 清理时设置为 null,建议统一使用 nullundefined
🔎 建议的类型和一致性改进
-  const timer = useRef<any>(undefined);
+  const timer = useRef<ReturnType<typeof setTimeout> | null>(null);

相应地,在清理时保持使用 null(line 19 已经是 null),这样初始值和清理值保持一致。

说明ReturnType<typeof setTimeout> 在 Node.js 环境返回 NodeJS.Timeout,在浏览器环境返回 number,提供了跨环境的类型安全性。

根据编码规范要求,避免使用 any 类型并精确定义类型。

src/utils/hooks/useDeepCompareEffect/index.ts (1)

9-18: 可考虑为 ref 添加显式类型注解。

虽然当前实现功能正常,但可以考虑为 ref 添加显式类型注解以提升类型安全性,例如:

const ref = useRef<typeof value | undefined>(undefined);

这样可以更好地符合编码规范中"尽可能精确定义类型"的要求。

根据编码规范,应避免使用 any 类型并尽可能精确定义类型。

src/field/components/Cascader/index.tsx (1)

50-50: React 19 合规性变更正确。

此变更符合 React 19 的要求,useRef 必须提供参数。运行时行为保持不变,因为 line 56 的 cascaderRef.current || {} 已正确处理 undefined 情况。

建议添加显式类型注解以提升类型安全性和 IDE 支持:

🔎 建议添加显式类型注解
-  const cascaderRef = useRef(undefined);
+  const cascaderRef = useRef<React.ElementRef<typeof Cascader> | undefined>(undefined);

注:由于 PR 说明中提到会后续修复类型错误,此改进可以在类型修复阶段一并处理。

基于 learnings 和 React 19 文档要求。

src/layout/components/SettingDrawer/LayoutChange.tsx (1)

9-11: 避免使用 as any 类型断言,应定义精确的类型。

使用 as any 绕过了 TypeScript 的类型检查,降低了代码的类型安全性。根据项目编码规范,应该"避免使用 any 类型,尽可能精确地定义类型"。

建议的改进方案:

  1. 方案一(推荐):为 action 元素定义具体的 props 类型
  2. 方案二:使用 React.cloneElement 的泛型参数明确类型
  3. 方案三:使用 React 19 官方提供的 codemod 工具处理类型迁移

基于编码规范:"Avoid using any type, define types as precisely as possible"

🔎 推荐的类型安全改进方案

方案一:定义具体的 props 类型

 export const renderLayoutSettingItem = (item: SettingItemProps) => {
-  const action = React.cloneElement(item.action, {
+  const action = React.cloneElement<React.ComponentProps<typeof item.action.type> & { disabled?: boolean }>(
+    item.action,
+    {
-    disabled: item.disabled,
-  } as any);
+      disabled: item.disabled,
+    }
+  );
   return (

方案二:使用更明确的类型断言

 export const renderLayoutSettingItem = (item: SettingItemProps) => {
   const action = React.cloneElement(item.action, {
     disabled: item.disabled,
-  } as any);
+  } as Partial<React.ComponentProps<typeof item.action.type>>);
   return (
src/field/components/Checkbox/index.tsx (1)

63-63: React 19 兼容性更改正确,建议添加显式类型参数。

useRef() 改为 useRef(undefined) 符合 React 19 的要求(useRef 现在必须提供参数)。不过建议添加显式类型参数以提高类型安全性。

🔎 建议的类型改进
-  const checkBoxRef = useRef(undefined);
+  const checkBoxRef = useRef<{ fetchData?: (keyWord: string) => void }>(undefined);

可选:考虑移除未使用的 ref。

注意到 checkBoxRef 从未被连接到任何组件(没有 ref={checkBoxRef} 传递给 Checkbox.Group),这意味着 checkBoxRef.current 始终为 undefined,第 67 行的扩展操作实际上总是使用空对象。如果这个 ref 没有实际用途,可以考虑移除它以简化代码。

根据学习记录,组件 ref 类型应该使用 React.ForwardRefRenderFunction 显式定义。

src/table/components/EditableTable/index.tsx (1)

137-152: 建议减少 as any 类型断言的使用。

当前使用 as any 访问 children.props 会丧失类型安全。根据编码指南,应尽量避免使用 any 类型。

可以考虑为 children 定义更精确的类型,或者使用类型守卫:

🔎 可选的类型改进方案
 function RecordCreator<T = Record<string, any>>(
-  props: RecordCreatorProps<T> & { children: React.ReactElement },
+  props: RecordCreatorProps<T> & { 
+    children: React.ReactElement<{ onClick?: (e: React.MouseEvent) => void | Promise<boolean | void> }> 
+  },
 ) {
   const { children, record, position, newRecordType, parentKey } = props;
   const actionRef = useContext(EditableTableActionContext);

   return React.cloneElement(children, {
-    ...(children.props as any),
+    ...children.props,
     onClick: async (e: any) => {
       // 如果返回了false,接触掉默认行为
-      const isOk = await (children.props as any)?.onClick?.(e);
+      const isOk = await children.props?.onClick?.(e);
       if (isOk === false) return;

不过考虑到 React.cloneElement 的通用性和实际使用场景的多样性,当前的 as any 方案也是可接受的折中方案。

src/utils/useEditableArray/index.tsx (1)

1109-1111: 类型定义更加精确。

SaveEditableActionRef<any> 添加 | null 使类型定义更准确,因为 ref 的 current 可能为 null。代码在第 1158 行已经处理了这种情况(if (!saveRef?.current)),所以这个类型变更提高了类型安全性。

💡 可选的优化建议

考虑将 any 替换为更具体的泛型类型以提高类型安全性:

-const saveRefsMap = useRef(
-  new Map<React.Key, React.RefObject<SaveEditableActionRef<any> | null>>(),
-);
+const saveRefsMap = useRef(
+  new Map<React.Key, React.RefObject<SaveEditableActionRef<RecordType> | null>>(),
+);
src/form/components/List/ListItem.tsx (1)

399-400: 建议改进类型安全性

使用 as any 类型断言绕过了类型检查,虽然这可能是为了兼容 React 19 中 ReactElement["props"]any 变为 unknown 的改动,但违反了项目编码规范中"避免使用 any 类型"的要求。

建议定义一个明确的接口来描述期望的 props 结构,例如:

interface ChildItemProps {
  name?: string | number;
  [key: string]: any;
}

// 然后使用
(childrenItem?.props as ChildItemProps)?.name

或者使用类型守卫函数来更安全地访问 name 属性。

根据编码规范。

src/form/components/FormItem/Group/index.tsx (1)

101-104: 建议使用更精确的类型定义替代 as any

使用 as any 类型断言会完全绕过 TypeScript 的类型检查,降低了代码的类型安全性。建议定义一个包含 hidden 属性的接口来替代:

🔎 建议的类型定义

在文件顶部添加接口定义:

+interface ProFormItemProps {
+  hidden?: boolean;
+  [key: string]: any;
+}

然后修改类型断言:

 if (
   React.isValidElement(element) &&
-  (element?.props as any)?.hidden
+  (element?.props as ProFormItemProps)?.hidden
 ) {

根据编码规范,应避免使用 any 类型,尽可能精确定义类型。

demos/table/EditableTable/form-linkage.tsx (1)

62-64: Ref 初始化正确,但建议改进泛型类型。

三个 ref 的显式 undefined 初始化符合 React 19 要求,与代码中的可选链用法一致。

但 Line 62 的 ProFormInstance<any> 使用了 any 类型。根据编码规范,应避免使用 any,尽可能精确定义类型。

🔎 建议的类型优化

由于表单已经定义了明确的类型结构(Line 173-175),建议使用精确类型:

+type FormValuesType = {
+  table: DataSourceType[];
+};
+
-const formRef = useRef<ProFormInstance<any>>(undefined);
+const formRef = useRef<ProFormInstance<FormValuesType>>(undefined);

这样可以在使用 formRef.current?.getFieldValue() 时获得更好的类型推断和类型安全。

根据编码规范:避免使用 any 类型,定义类型尽可能精确。

src/layout/components/AppsLogoComponents/index.tsx (1)

55-55: 验证类型断言的必要性

popoverRef 在第 48 行已经正确定义为 React.useRef<HTMLSpanElement>(null),其类型应该已经是 React.RefObject<HTMLSpanElement>。此处的类型断言可能是冗余的。

建议验证是否真的需要这个类型断言,或者是否可以通过调整 onItemClick 的类型定义来避免。

🔎 如果类型断言确实是冗余的,可以考虑移除
  const cloneItemClick = (app: AppItemProps) => {
-    itemClick?.(app, popoverRef as React.RefObject<HTMLSpanElement>);
+    itemClick?.(app, popoverRef);
  };
src/layout/components/SettingDrawer/ThemeColor.tsx (1)

12-18: 考虑统一组件的 ref 处理方式。

ThemeColor 组件已从 ForwardRefRenderFunction 简化为 React.FC(符合 React 19 的改进),但同一文件中的 Tag 组件仍在使用 React.forwardRef。为保持代码风格一致性,建议同步更新 Tag 组件。

🔎 建议的 Tag 组件简化方案
-const Tag: React.FC<TagProps> = React.forwardRef(
-  ({ color, check, ...rest }, ref) => (
-    <div {...rest} style={{ backgroundColor: color }} ref={ref as any}>
+const Tag: React.FC<TagProps & { ref?: React.Ref<HTMLDivElement> }> = ({ 
+  color, 
+  check, 
+  ref,
+  ...rest 
+}) => (
+    <div {...rest} style={{ backgroundColor: color }} ref={ref}>
      {check ? <CheckOutlined /> : ''}
    </div>
-  ),
-);
+  );

Also applies to: 33-40

src/form/BaseForm/LightWrapper/index.tsx (1)

144-151: 考虑改进子元素的类型安全性。

使用 as any 类型断言降低了类型安全性。虽然这简化了代码,但可能在编译时遗漏潜在的类型错误。

🔎 建议的类型安全改进
-        {React.cloneElement(children as any, {
+        {React.isValidElement(children) && React.cloneElement(children, {
          ...rest,
          [valuePropName!]: tempValue,
          onChange: (e: any) => {
            setTempValue(e?.target ? e.target.value : e);
          },
-          ...((children as any)?.props || {}),
+          ...(children.props || {}),
        })}

此改进方案:

  1. 使用 React.isValidElement 进行运行时检查
  2. 移除不必要的类型断言
  3. 保持现有的空值安全处理
src/layout/components/GlobalHeader/ActionsContent.tsx (1)

75-75: 建议使用更精确的类型断言而非 any

虽然此更改解决了 React 19 中 ReactElement["props"] 默认为 unknown 的类型问题,但使用 as any 会削弱类型安全。由于 aria-hidden 是标准的 HTML 属性,建议使用更精确的类型断言。

🔎 建议的改进方案
-                  hideHover = !!(dom?.props as any)?.['aria-hidden'];
+                  hideHover = !!(dom?.props as React.HTMLAttributes<any>)?.['aria-hidden'];

或者,如果需要支持更多属性类型:

-                  hideHover = !!(dom?.props as any)?.['aria-hidden'];
+                  hideHover = !!((dom?.props as { 'aria-hidden'?: boolean })?.['aria-hidden']);
src/field/FieldHOC/index.tsx (1)

44-47: 考虑使用更具体的类型而非 any

将类型断言从 JSX.Element 改为 any 会削弱类型安全性。虽然这样可以绕过 React 19 中 JSX.Element 类型定义的变更,但建议考虑使用 React.ReactElement 作为替代方案,以保持更好的类型检查。

🔎 建议的类型改进
-        {React.cloneElement(props.children as any, {
+        {React.cloneElement(props.children as React.ReactElement, {
           labelTrigger,
           lightLabel,
         })}

或者,在 props 接口中明确定义 children 的类型:

 function FieldHOC<T extends ProFieldLightProps>(
   props: T & {
-    children: React.ReactNode;
+    children: React.ReactElement;
     isLight?: boolean;
   },
 ) {

然后移除类型断言:

-        {React.cloneElement(props.children as any, {
+        {React.cloneElement(props.children, {
           labelTrigger,
           lightLabel,
         })}
src/form/layouts/ModalForm/index.tsx (1)

137-137: 考虑改进类型安全性。

在 Lines 137 和 140 使用 as any 类型断言会降低类型安全性,可能隐藏潜在的类型错误。

🔎 建议的类型改进

考虑为 trigger props 定义更精确的类型:

+type TriggerProps = {
+  onClick?: (e: React.MouseEvent) => void;
+  [key: string]: any;
+};
+
 const triggerDom = useMemo(() => {
   if (!trigger) {
     return null;
   }

   return React.cloneElement(trigger, {
     key: 'trigger',
-    ...(trigger.props as any),
+    ...(trigger.props as TriggerProps),
     onClick: async (e: any) => {
       setOpen(!open);
-      (trigger.props as any)?.onClick?.(e);
+      (trigger.props as TriggerProps)?.onClick?.(e);
     },
   });
 }, [setOpen, trigger, open]);

Also applies to: 140-140

src/form/BaseForm/BaseForm.tsx (1)

423-423: 类型断言降低了类型安全性。

使用 ...(item.props as any) 会绕过 TypeScript 的类型检查。

🔎 建议的类型改进

考虑定义更精确的 props 类型:

 const items = useMemo(() => {
   return React.Children.toArray(children as any).map((item, index) => {
     if (index === 0 && React.isValidElement(item) && autoFocusFirstInput) {
       return React.cloneElement(item, {
-        ...(item.props as any),
+        ...item.props,
         autoFocus: autoFocusFirstInput,
-      });
+      } as React.ReactElement<any>);
     }
     return item;
   });
 }, [autoFocusFirstInput, children]);

或者,如果类型冲突是由于 React 19 的严格类型检查,可以添加注释说明原因。

src/layout/ProLayout.tsx (1)

106-109: 可选优化:logo 类型声明

logo 类型中同时包含 React.ReactNodeReact.ReactElement。由于 React.ReactElementReact.ReactNode 的子集,这个联合类型可以简化。不过当前声明是有效的,不影响功能。

可选的类型简化
  logo?:
    | React.ReactNode
-    | React.ReactElement
    | WithFalse<() => React.ReactNode | React.ReactElement>;
tests/field/field.test.tsx (3)

1465-1465: 建议使用更精确的类型替代 any

根据编码规范,应避免使用 any 类型。建议使用 boolean 类型,因为 onOpenChange 的参数应该是布尔值。

🔎 建议的修改
-        onOpenChange={(open: any) => fn(open)}
+        onOpenChange={(open: boolean) => fn(open)}

1630-1630: 建议使用更精确的类型。

根据编码规范,应避免使用 any 类型。

🔎 建议的修改
-        onChange={(value: any) => change(value)}
+        onChange={(value: string) => change(value)}

1927-1927: 建议使用更精确的类型。

根据编码规范,应避免使用 any 类型。可以定义具体的参数类型。

🔎 建议的修改
-        request={async (params: any) => {
+        request={async (params: { test?: string }) => {

*/
export function useActionType<T>(
ref: React.MutableRefObject<ActionType | undefined>,
ref: React.RefObject<ActionType | undefined>,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

类型不匹配:RefObject 与可变赋值冲突

RefObject<T>current 属性是只读的,但在第 136 行代码中直接对 ref.current 进行了赋值操作(ref.current = userAction)。这会导致 TypeScript 编译错误。

如果需要在函数内部修改 ref 的值,应该使用 React.MutableRefObject<ActionType | undefined> 而不是 React.RefObject

🔎 建议的修复方案
 export function useActionType<T>(
-  ref: React.RefObject<ActionType | undefined>,
+  ref: React.MutableRefObject<ActionType | undefined>,
   action: UseFetchDataAction<T>,
   props: {
     nativeElement?: HTMLDivElement;
     focus?: () => void;
     fullScreen: () => void;
     onCleanSelected: () => void;
     resetAll: () => void;
     editableUtils: UseEditableUtilType;
     /** 透传给 ActionType 的滚动能力 */
     scrollTo?: ActionType['scrollTo'];
   },
 ) {

或者,如果确实要使用 RefObject,需要移除第 136 行的赋值操作,并调整架构以避免直接修改 ref。

🤖 Prompt for AI Agents
In src/table/utils/index.ts around lines 88–136, the function accepts ref:
React.RefObject<ActionType | undefined> but the code assigns to ref.current at
line 136, causing a TS error because RefObject.current is readonly; change the
parameter type to React.MutableRefObject<ActionType | undefined> (and import
MutableRefObject if needed) so current can be mutated, or alternatively remove
the assignment and refactor to use a callback ref or component state to expose
the ActionType without mutating a RefObject.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
src/provider/index.tsx (1)

136-156: 应使用 React.ReactNode 保持类型一致性,而非 React.ReactElement

项目的 peerDependencies 要求 react: >=18.0.0,并不支持 React 16,因此无需考虑 React 16 兼容性。

然而,将 dom 参数类型设为 React.ReactElement 存在一个问题:在相同项目中,其他类似的 render 方法(如 SiderMenuGlobalHeader 中的 render 属性)均使用 React.ReactNode 作为 dom 参数类型。使用 React.ReactElementReact.ReactNode 更加严格,会限制开发者的灵活性(例如无法返回 Fragment 或字符串)。

建议将 dom 参数类型统一改为 React.ReactNode,以保持整个代码库的一致性。

src/table/components/Form/FormRender.tsx (1)

230-230: 类型错误:尝试赋值给只读属性

第 230 行尝试给 formRef.current 赋值,但 formRef 在第 106 行被定义为 React.RefObject,其 .current 属性是只读的。这会导致 TypeScript 编译错误。

建议的解决方案:

  1. 如果 formRef 需要在内部赋值,考虑在组件内部使用独立的可变 ref,然后通过 useImperativeHandle 或其他机制同步
  2. 或者检查是否可以移除这行赋值,因为 formRef 已经在调用 BetaSchemaForm 时作为 prop 传递(第 226 行),表单组件应该自行管理 ref
🔎 建议的修复方案

方案 1:使用内部可变 ref

 const FormRender = <T, U = any>({
   onSubmit,
   formRef,
   dateFormatter = 'string',
   type,
   columns,
   action,
   ghost,
   manualRequest,
   onReset,
   submitButtonLoading,
   search: searchConfig,
   form: formConfig,
   bordered,
 }: TableFormItem<T, U>) => {
+  const internalFormRef = useRef<ProFormInstance>();
   const { hashId } = useContext(ProProvider);
   // ... rest of the code
   
         onInit={(values: T, form) => {
-          formRef.current = form;
+          internalFormRef.current = form;
+          // 如果外部 formRef 需要访问,可以使用其他方式同步
           // 触发一个 submit,之所以这里触发是为了保证 value 都被 format了

方案 2:移除赋值(如果 BetaSchemaForm 已经处理了 formRef)

         onInit={(values: T, form) => {
-          formRef.current = form;
           // 触发一个 submit,之所以这里触发是为了保证 value 都被 format了
src/layout/ProLayout.tsx (1)

245-250: RefObject 改为 MutableRefObject

actionRef 的类型定义为 React.RefObject,但第 539 行直接对 actionRef.current 进行赋值。由于 RefObjectcurrent 属性被定义为 readonly,在启用 strict: true 的 TypeScript 编译器下,这会导致类型错误:"Cannot assign to 'current' because it is a readonly property"。

应将第 245 行的类型定义改为 React.MutableRefObject 以支持可变的引用,或使用 useImperativeHandle 等 React Hooks 来管理 ref 的值。

src/form/components/FormItem/index.tsx (1)

51-60: 修复返回类型声明与静态分析错误。

该函数声明返回类型为 void,但第 54 行显式返回了 undefined。虽然在 JavaScript 运行时 voidundefined 相似,但在 TypeScript 中这是不正确的。void 类型表示函数不应返回任何值,而显式返回 undefined 违反了这一约定。

此外,第 55、57 行使用 as any 类型断言来访问 filedChildren.props,这会绕过 TypeScript 的类型检查,可能导致运行时错误。

🔎 建议的修复方案
  1. 移除显式的 return undefined 语句:
 const onChangeMemo = useRefFunction(function (...restParams: any[]): void {
   onChange?.(...restParams);
   if (isProFormComponent) return;
-  if (isValidElementForFiledChildren) return undefined;
+  if (isValidElementForFiledChildren) return;
   (filedChildren?.props as any)?.onChange?.(...restParams);
  1. 考虑为 filedChildren 定义更精确的类型,而不是使用 as any
-  (filedChildren?.props as any)?.onChange?.(...restParams);
+  if (React.isValidElement(filedChildren) && 'onChange' in filedChildren.props) {
+    (filedChildren.props as { onChange?: (...args: any[]) => void }).onChange?.(...restParams);
+  }

根据静态分析工具提示。

🧹 Nitpick comments (18)
src/layout/components/GlobalHeader/ActionsContent.tsx (2)

74-76: 建议优化类型断言或添加注释说明。

此更改添加了 as any 类型断言以适配 React 19 中 ReactElement["props"] 默认为 unknown 的类型变化。虽然在处理来自消费者代码的任意元素时可能不可避免,但这降低了类型安全性。

建议考虑以下选项之一:

  1. 使用更安全的类型检查方式:
const props = dom.props as Record<string, unknown>;
hideHover = !!(props?.['aria-hidden']);
  1. 如果必须使用 as any,添加注释说明原因:
// React 19: props 类型为 unknown,需要类型断言以访问任意属性
hideHover = !!(dom?.props as any)?.['aria-hidden'];

请验证此模式是否与整体 React 19 升级策略一致。

基于编码规范:"避免使用 any 类型,尽可能精确地定义类型"。


52-52: 建议为 restParams 定义精确类型。

当前使用 any 类型降低了类型安全性。建议基于 GlobalHeaderProps 定义一个精确的类型:

type ActionsRenderParams = Omit<GlobalHeaderProps, 'avatarProps' | 'actionsRender' | 'headerContentRender'> & {
  rightContentSize?: number | string;
};

const rightActionsRender =
  actionsRender || avatarDom
    ? (restParams: ActionsRenderParams) => {
        // ...
      }
    : undefined;

基于编码规范:"避免使用 any 类型,尽可能精确地定义类型"和"所有回调函数类型应明确定义参数和返回值"。

src/field/components/Cascader/index.tsx (1)

50-50: 建议为 cascaderRef 添加显式类型声明

虽然显式传入 undefined 符合 React 19 要求,但与 PR 中其他文件不同,此处未提供类型参数。建议添加显式类型以提高类型安全性和代码可维护性。

🔎 建议的类型改进
-  const cascaderRef = useRef(undefined);
+  const cascaderRef = useRef<any>(undefined);

或者,如果能获取到 Cascader 组件的 ref 类型,使用更精确的类型:

const cascaderRef = useRef<React.ElementRef<typeof Cascader>>(undefined);

根据代码规范,组件 ref 类型应当显式定义。

demos/form/FieldSet/captCha.tsx (1)

14-15: 建议添加明确的类型参数以提升类型安全

这两个 ref 缺少类型参数,导致在使用时需要 // @ts-ignore 注释(Lines 27, 37)。建议为 ref 添加适当的类型定义以消除类型忽略并提升代码质量。

🔎 建议的类型改进
+// 定义 captcha ref 的类型接口
+interface CaptchaFieldRef {
+  startTiming: () => void;
+  endTiming: () => void;
+}
+
 const Demo = () => {
-  const captchaRef = useRef(undefined);
-  const inputRef = useRef(undefined);
+  const captchaRef = useRef<CaptchaFieldRef>(undefined);
+  const inputRef = useRef<HTMLInputElement>(undefined);

   return (
     <ProForm
       title="新建表单"
       submitter={{
         render: (props, doms) => {
           return [
             ...doms,
             <Button
               htmlType="button"
               onClick={() => {
-                // @ts-ignore
                 captchaRef.current?.startTiming();
               }}
               key="edit"
             >
               手动开始计数
             </Button>,
             <Button
               htmlType="button"
               onClick={() => {
-                // @ts-ignore
                 captchaRef.current?.endTiming();
               }}
               key="edit2"
             >
               手动结束计数
             </Button>,
           ];
         },
       }}
demos/form/FieldSet/pro-form-captCha.tsx (1)

16-16: 建议为 inputRef 添加显式类型注解

Line 16 的 inputRef 初始化缺少类型参数,TypeScript 会将其推断为 React.MutableRefObject<undefined>,这可能不是预期的类型。由于该 ref 通过 fieldProps.ref 传递给输入组件(Line 64),建议添加显式的 HTML 元素类型注解。

🔎 建议的类型注解改进
-  const inputRef = useRef(undefined);
+  const inputRef = useRef<HTMLInputElement>(undefined);
src/utils/useEditableArray/index.tsx (1)

1117-1117: 说明忽略 ref 值的原因

useEffect 的迭代从 (ref, key) 改为 (_, key),不再使用 ref 值。虽然当前逻辑中确实不需要 ref 值(仅用于删除 key),但建议添加注释说明为何忽略该参数,以提高代码可读性。

🔎 建议的注释
-    saveRefsMap.current.forEach((_, key) => {
+    // 只需要 key 来判断是否需要删除,ref 值在此处不使用
+    saveRefsMap.current.forEach((_, key) => {
src/form/components/FormItem/Group/index.tsx (1)

101-104: 避免使用 as any 绕过类型检查

使用 (element?.props as any)?.hidden 会绕过 TypeScript 的类型安全检查。建议使用类型守卫或更精确的类型定义来访问 hidden 属性。

🔎 推荐的重构方案

方案一:使用类型守卫

+const hasHiddenProp = (
+  element: React.ReactElement
+): element is React.ReactElement<{ hidden?: boolean }> => {
+  return 'hidden' in (element.props || {});
+};
+
 const [childrenDoms, hiddenDoms] = useMemo(() => {
   const hiddenChildren: React.ReactNode[] = [];
   const childrenList = React.Children.toArray(children).map(
     (element, index) => {
       if (
         React.isValidElement(element) &&
-        (element?.props as any)?.hidden
+        hasHiddenProp(element) &&
+        element.props.hidden
       ) {
         hiddenChildren.push(element);
         return null;
       }

方案二:使用 in 运算符检查

       if (
         React.isValidElement(element) &&
-        (element?.props as any)?.hidden
+        'hidden' in (element?.props || {}) &&
+        (element.props as { hidden?: boolean }).hidden
       ) {
src/form/components/List/ListItem.tsx (1)

399-400: 建议使用更具体的类型而非 any

使用 as any 绕过了 React 19 中更严格的类型检查(ReactElement["props"] 现在默认为 unknown)。虽然这能正常工作,但牺牲了类型安全性。

🔎 建议的改进方案

如果子元素的 props 结构是已知的(比如包含 name 属性的表单字段),可以定义一个接口并使用更精确的类型断言:

+interface ChildPropsWithName {
+  name?: string | number;
+  [key: string]: any;
+}
+
  .map((childrenItem, itemIndex) => {
    if (React.isValidElement(childrenItem)) {
      return React.cloneElement(childrenItem, {
        key:
-         childrenItem.key || (childrenItem?.props as any)?.name || itemIndex,
+         childrenItem.key || (childrenItem?.props as ChildPropsWithName)?.name || itemIndex,
        ...(childrenItem?.props || {}),
      });
    }

或者,如果 name 属性的存在性需要运行时检查:

  .map((childrenItem, itemIndex) => {
    if (React.isValidElement(childrenItem)) {
+     const childProps = childrenItem?.props as Record<string, unknown>;
+     const keyFromProps = typeof childProps?.name === 'string' || typeof childProps?.name === 'number' 
+       ? childProps.name 
+       : undefined;
      return React.cloneElement(childrenItem, {
        key:
-         childrenItem.key || (childrenItem?.props as any)?.name || itemIndex,
+         childrenItem.key || keyFromProps || itemIndex,
        ...(childrenItem?.props || {}),
      });
    }
src/layout/components/SettingDrawer/LayoutChange.tsx (1)

9-11: 建议使用更安全的类型断言方式。

当前使用 as any 完全绕过了类型检查,可能会隐藏潜在的类型错误。建议考虑以下更安全的替代方案:

  1. 使用条件类型检查 action 是否支持 disabled 属性
  2. 定义明确的 action 类型约束,确保所有 action 元素都支持 disabled
🔎 建议的类型安全改进
 export const renderLayoutSettingItem = (item: SettingItemProps) => {
   const action = React.cloneElement(item.action, {
     disabled: item.disabled,
-  } as any);
+  } as React.HTMLAttributes<any>);
   return (

或者,在 SettingItemProps 接口中明确定义 action 的类型:

interface SettingItemProps {
  action: React.ReactElement<{ disabled?: boolean }>;
  disabled?: boolean;
  // ... 其他属性
}
src/form/layouts/DrawerForm/index.tsx (1)

183-191: 建议改进类型断言的使用

在克隆 trigger 元素时,使用了 as any 类型断言来访问 props(第 185 和 189 行)。虽然这在动态元素克隆场景中可以工作,但会降低类型安全性。

考虑定义一个更具体的类型来替代 any,例如:

type TriggerProps = {
  onClick?: (e: any) => void;
  [key: string]: any;
};

然后使用 trigger.props as TriggerProps,这样可以在保持灵活性的同时提供基本的类型检查。

src/form/layouts/QueryFilter/index.tsx (1)

245-245: 类型更新正确,但类型断言使用频繁

submitter 属性类型更新为 React.ReactElement | false 符合 React 19 要求。但在多处使用 as any 访问 props(第 311、334、400 行)降低了类型安全性。

由于这些组件处理动态的 React 元素和子元素,完全的类型安全可能难以实现。但建议考虑:

  1. 为常用的 props(如 colSizenamehidden)定义接口
  2. 使用联合类型而不是完全放弃类型检查

这与 DrawerForm 中的模式一致,表明这是项目范围内的权衡取舍。

Also applies to: 311-311, 334-334, 400-400

src/table/components/EditableTable/index.tsx (1)

132-132: 建议改进类型安全性

children 类型从 JSX.Element 更改为 React.ReactElement 是正确的,但随后使用 as any 类型断言绕过了类型检查,这可能会隐藏潜在的类型错误。

建议定义更精确的类型:

🔎 建议的类型改进
 function RecordCreator<T = Record<string, any>>(
-  props: RecordCreatorProps<T> & { children: React.ReactElement },
+  props: RecordCreatorProps<T> & { 
+    children: React.ReactElement<{ onClick?: (e: any) => void | boolean | Promise<void | boolean> }>
+  },
 ) {
   const { children, record, position, newRecordType, parentKey } = props;
   const actionRef = useContext(EditableTableActionContext);

   return React.cloneElement(children, {
-    ...(children.props as any),
+    ...children.props,
     onClick: async (e: any) => {
       // 如果返回了false,接触掉默认行为
-      const isOk = await (children.props as any)?.onClick?.(e);
+      const isOk = await children.props?.onClick?.(e);
       if (isOk === false) return;

       if (actionRef?.current) {
         actionRef.current.addEditRecord(record as any, {
           position,
           newRecordType,
           parentKey: parentKey as React.Key,
         });
       }
     },
   });
 }

Also applies to: 138-138, 141-141

tests/field/field.test.tsx (1)

648-648: 测试中的类型注解

为测试回调函数添加显式类型注解以满足 React 19 更严格的类型检查。虽然使用了 any 类型,但在测试代码中这是可以接受的权衡。

如果时间允许,可以考虑使用更具体的类型来提高类型安全性,但这不是必需的。

可选的类型改进示例

例如对于 Line 1630,可以使用更具体的类型:

-        onChange={(value: any) => change(value)}
+        onChange={(value: string | number | undefined) => change(value)}

Also applies to: 1465-1465, 1489-1489, 1554-1554, 1630-1630, 1927-1927

src/form/layouts/StepsForm/index.tsx (1)

129-133: 建议移除 as any 类型断言。

React.cloneElement 中使用 as any 会抑制类型检查,可能会掩盖真正的类型错误。建议明确指定正确的 props 类型,或者验证 style 属性是否与 stepsDom 的类型兼容。

🔎 建议的改进方案

移除类型断言并显式类型化 props:

-          {React.cloneElement(stepsDom, {
-            style: {
-              height: '100%',
-            },
-          } as any)}
+          {React.cloneElement(stepsDom, {
+            style: {
+              height: '100%',
+            },
+          })}

如果遇到类型错误,请根据实际的 stepsDom 类型(应该是 React.ReactElement)来调整。

src/form/components/FormItem/index.tsx (3)

62-70: 建议改进类型安全性。

第 66 行使用 as any 类型断言访问 filedChildren.props.onBlur,这会绕过类型检查。建议使用类型守卫或更精确的类型定义来替代 as any

🔎 建议的改进方案
-  (filedChildren?.props as any)?.onBlur?.(...restParams);
+  if (React.isValidElement(filedChildren) && 'onBlur' in filedChildren.props) {
+    (filedChildren.props as { onBlur?: (...args: any[]) => void }).onBlur?.(...restParams);
+  }

123-133: 建议移除 props 展开时的类型断言。

第 128 行在展开 filedChildren.props 时使用了 as any 断言。如果 filedChildrenReact.ReactElement,其 props 应该已有正确的类型,无需使用 as any。这可能会掩盖 props 类型不兼容的问题。

🔎 建议的改进方案
   return React.cloneElement(
     filedChildren,
     omitUndefined({
       ...restProps,
       [valuePropName]: formFieldProps[valuePropName],
-      ...(filedChildren.props as any),
+      ...filedChildren.props,
       onChange: finalChange,
       fieldProps,
       onBlur: isProFormComponent && !isValidElementForFiledChildren && onBlur,
     }),
   );

如果遇到类型错误,应该明确定义 filedChildren 的类型,而不是使用 as any 绕过。


370-372: 建议改进 valueType 访问的类型安全性。

第 372 行使用 as any 断言访问 props.children.props.valueType。建议添加类型守卫以确保 valueType 属性存在且类型正确。

🔎 建议的改进方案
   const isDropdown =
     React.isValidElement(props.children) &&
-    isDropdownValueType(valueType || (props.children.props as any).valueType);
+    isDropdownValueType(
+      valueType || 
+      (React.isValidElement(props.children) && 
+       'valueType' in props.children.props ? 
+       (props.children.props as { valueType?: unknown }).valueType : 
+       undefined)
+    );
src/field/components/Radio/index.tsx (1)

28-28: React 19 兼容性改动正确。

useRef() 改为 useRef(undefined) 符合 React 19 的要求(useRef 现在需要参数)。虽然可以添加显式类型注解以提高类型安全性,但当前模式在代码库中一致使用(如 Cascader、Checkbox、Select 等字段组件),且 TypeScript 能从 Radio.Group 的使用推断出类型。如果要统一类型注解风格,可参考已有的模式:

-  const radioRef = useRef(undefined);
+  const radioRef = useRef<React.ElementRef<typeof Radio.Group> | undefined>(undefined);

不过此改动非必需。


/** 一些简单的操作 */
actionRef?: React.MutableRefObject<ProCoreActionType<any> | undefined>;
actionRef?: React.RefObject<ProCoreActionType<any> | undefined>;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, check the file size and structure
wc -l src/descriptions/index.tsx

Repository: ant-design/pro-components

Length of output: 99


🏁 Script executed:

#!/bin/bash
# Read the relevant sections mentioned in the review comment
echo "=== Line 101 (actionRef definition) ==="
sed -n '95,110p' src/descriptions/index.tsx

echo -e "\n=== Lines 527-532 (actionRef assignment) ==="
sed -n '520,540p' src/descriptions/index.tsx

echo -e "\n=== Lines 323, 391, 449, 452 (other mentioned changes) ==="
sed -n '320,330p' src/descriptions/index.tsx
sed -n '388,395p' src/descriptions/index.tsx
sed -n '445,455p' src/descriptions/index.tsx

Repository: ant-design/pro-components

Length of output: 2038


🏁 Script executed:

#!/bin/bash
# Search for all actionRef assignments in the file to understand usage patterns
rg -n 'actionRef' src/descriptions/index.tsx -A 2 -B 2

Repository: ant-design/pro-components

Length of output: 739


🏁 Script executed:

#!/bin/bash
# Check for any type casting or suppression around the actionRef assignment
sed -n '525,535p' src/descriptions/index.tsx | cat -n

Repository: ant-design/pro-components

Length of output: 369


🏁 Script executed:

#!/bin/bash
# Search for ProCoreActionType definition to understand the type structure
rg -n 'type ProCoreActionType|interface ProCoreActionType' --type=ts --type=tsx

Repository: ant-design/pro-components

Length of output: 96


🏁 Script executed:

#!/bin/bash
# Check if there's a useRef hook being used and how actionRef is passed in
rg -n 'useRef.*actionRef|actionRef.*useRef' src/descriptions/ --type=ts --type=tsx -B 2 -A 2

Repository: ant-design/pro-components

Length of output: 96


🏁 Script executed:

#!/bin/bash
# Search for ProCoreActionType definition
rg -n 'ProCoreActionType' --type ts -A 5 | head -50

Repository: ant-design/pro-components

Length of output: 2597


🏁 Script executed:

#!/bin/bash
# Search with broader pattern for the type definition
rg 'type ProCoreActionType|interface ProCoreActionType' -A 5

Repository: ant-design/pro-components

Length of output: 403


🏁 Script executed:

#!/bin/bash
# Check how actionRef is being used as a parameter in the component
sed -n '475,495p' src/descriptions/index.tsx | cat -n

Repository: ant-design/pro-components

Length of output: 546


🏁 Script executed:

#!/bin/bash
# Look at the complete function signature to understand the parameters
head -120 src/descriptions/index.tsx | tail -50

Repository: ant-design/pro-components

Length of output: 1223


🏁 Script executed:

#!/bin/bash
# Check if there are any type assertions or workarounds around the actionRef assignment
sed -n '525,535p' src/descriptions/index.tsx

Repository: ant-design/pro-components

Length of output: 292


🏁 Script executed:

#!/bin/bash
# Look at the complete usage to see if actionRef is cast to MutableRefObject anywhere
rg -n 'as.*MutableRefObject|as.*Ref' src/descriptions/index.tsx -B 2 -A 2

Repository: ant-design/pro-components

Length of output: 51


🏁 Script executed:

#!/bin/bash
# Check the tsconfig to see if there are any type checking relaxations
cat tsconfig.json | grep -A 10 '"compilerOptions"'

Repository: ant-design/pro-components

Length of output: 378


🏁 Script executed:

#!/bin/bash
# Check if useImperativeHandle or other patterns are used
rg -n 'useImperativeHandle|forwardRef' src/descriptions/index.tsx -B 2 -A 5

Repository: ant-design/pro-components

Length of output: 51


🏁 Script executed:

#!/bin/bash
# Check the complete hook signature and return to understand the pattern better
sed -n '470,510p' src/descriptions/index.tsx | cat -n

Repository: ant-design/pro-components

Length of output: 1249


🏁 Script executed:

#!/bin/bash
# Verify if this is causing any actual TypeScript errors by checking if the file compiles
# Look for any build output or type checking results
rg -n 'MutableRefObject' src/descriptions/index.tsx

Repository: ant-design/pro-components

Length of output: 51


actionRef.current 赋值违反 RefObject 的只读约束

React.RefObject<T>current 属性是只读的(readonly),但第 528 行直接对其赋值,这在启用 strict: true 的 TypeScript 严格模式下会产生编译错误。

需要解决此兼容性问题:

  • 如果要支持赋值操作,应恢复使用 React.MutableRefObject<ProCoreActionType<any> | undefined>
  • 或重构 useEffect 中的逻辑以避免直接修改 current 属性
🤖 Prompt for AI Agents
In src/descriptions/index.tsx around line 101 (prop declaration) and the
assignment at line 528, the code assigns to actionRef.current which violates the
readonly contract of React.RefObject; either change the prop type to
React.MutableRefObject<ProCoreActionType<any> | undefined> so current is
writable, or refactor the effect to avoid direct assignment (e.g., create and
use a local mutable ref or expose a setter/callback prop and assign via that).
Update the prop type and any callers to accept MutableRefObject if choosing the
first option, or rewrite the useEffect to set state/call a setter instead of
mutating current if choosing the second.

Comment on lines +44 to 47
{React.cloneElement(props.children as any, {
labelTrigger,
lightLabel,
})}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

避免使用 any 类型断言,建议改用 React.ReactElement

将类型断言从 JSX.Element 改为 any 会失去类型安全性。根据 React 19 的类型系统更新,建议使用 React.ReactElement 代替 any

🔎 建议的类型安全重构
-        {React.cloneElement(props.children as any, {
+        {React.cloneElement(props.children as React.ReactElement, {
           labelTrigger,
           lightLabel,
         })}

根据编码规范:应尽量避免使用 any 类型,尽可能精确地定义类型。

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{React.cloneElement(props.children as any, {
labelTrigger,
lightLabel,
})}
{React.cloneElement(props.children as React.ReactElement, {
labelTrigger,
lightLabel,
})}
🤖 Prompt for AI Agents
In src/field/FieldHOC/index.tsx around lines 44 to 47, replace the unsafe "any"
type assertion when cloning children: ensure props.children is typed as
React.ReactElement (or React.ReactElement<PropsType> if you can specify the
child's prop types) and narrow-check it before calling React.cloneElement so
TypeScript knows it's an element; then call React.cloneElement(props.children as
React.ReactElement, { labelTrigger, lightLabel }) (or use a typed generic) to
preserve type safety and avoid any.

if (index === 0 && React.isValidElement(item) && autoFocusFirstInput) {
return React.cloneElement(item, {
...item.props,
...(item.props as any),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

类型断言降低了类型安全性。

使用 as any 来绕过类型检查会削弱 TypeScript 的类型保护。虽然这可能是 React 19 类型更新的临时解决方案,但建议:

  • 如果 item.props 有明确的类型定义,应使用更具体的类型断言
  • 或者定义一个适当的接口来描述预期的 props 结构
🔎 可能的改进方案
-          ...(item.props as any),
+          ...item.props,

如果类型错误是由于 React 19 的 ReactElement 类型更严格导致的,可以考虑定义更精确的类型:

type ValidElementProps = {
  autoFocus?: boolean;
  [key: string]: any;
};

// 然后使用
...(item.props as ValidElementProps),

基于编码指南,应避免使用 any 类型并尽可能精确地定义类型。

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
...(item.props as any),
...item.props,
🤖 Prompt for AI Agents
In src/form/BaseForm/BaseForm.tsx around line 423, change the unsafe "as any"
assertion when spreading item.props to a precise type: determine the expected
props shape (either define a ValidElementProps interface with explicit optional
fields like autoFocus and an index signature, or derive the props type from the
element type using React.ComponentPropsWithoutRef<typeof item.type> /
React.ComponentProps<typeof item.type>), replace "(item.props as any)" with a
cast to that specific type, and update imports/types accordingly so the spread
preserves type safety instead of using any.

Comment on lines +137 to +140
...(trigger.props as any),
onClick: async (e: any) => {
setOpen(!open);
trigger.props?.onClick?.(e);
(trigger.props as any)?.onClick?.(e);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

多处类型断言削弱了类型安全保障。

在克隆 trigger 元素时使用了两次 as any 断言(line 137 和 line 140),这会绕过 TypeScript 的类型检查。考虑以下改进:

  1. 定义明确的 trigger props 接口
  2. 使用更具体的类型而非 any
  3. 利用 React.ReactElement 的类型参数
🔎 建议的类型安全改进
+type TriggerProps = {
+  onClick?: (e: React.MouseEvent) => void;
+  [key: string]: any;
+};
+
 return React.cloneElement(trigger, {
   key: 'trigger',
-  ...(trigger.props as any),
+  ...trigger.props,
   onClick: async (e: any) => {
     setOpen(!open);
-    (trigger.props as any)?.onClick?.(e);
+    trigger.props.onClick?.(e);
   },
 });

基于编码指南,应避免使用 any 类型,并尽可能精确地定义类型。

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
...(trigger.props as any),
onClick: async (e: any) => {
setOpen(!open);
trigger.props?.onClick?.(e);
(trigger.props as any)?.onClick?.(e);
type TriggerProps = {
onClick?: (e: React.MouseEvent) => void;
[key: string]: any;
};
return React.cloneElement(trigger, {
key: 'trigger',
...trigger.props,
onClick: async (e: any) => {
setOpen(!open);
trigger.props.onClick?.(e);
},
});
🤖 Prompt for AI Agents
In src/form/layouts/ModalForm/index.tsx around lines 137-140, the code weakens
type safety by using two `as any` assertions when cloning the trigger element;
replace these with a properly typed approach: declare an explicit TriggerProps
interface (including optional onClick: (e: React.MouseEvent) => void and any
other used props), type the trigger as React.ReactElement<TriggerProps>, and
when cloning cast to that specific type (or use generics) instead of `any`; call
the typed onClick handler and spread the strongly typed props so TypeScript can
check correctness.


export function useDeepCompareMemoize(value: any, ignoreKeys?: any) {
const ref = useRef();
const ref = useRef(undefined);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

需要添加类型参数以确保正确的类型推断。

当前 useRef(undefined) 会被 TypeScript 推断为 MutableRefObject<undefined>。虽然第 14 行可以将 any 类型的 value 赋值给 ref.current,但 ref.current 的类型仍然是 undefined,导致第 17 行的返回类型被推断为 undefined 而不是预期的 any,这会引发类型错误。

🔎 建议的修复方案

方案 1(快速修复): 显式指定类型参数

-  const ref = useRef(undefined);
+  const ref = useRef<any>(undefined);

方案 2(推荐): 使用泛型实现类型安全

-export function useDeepCompareMemoize(value: any, ignoreKeys?: any) {
-  const ref = useRef(undefined);
+export function useDeepCompareMemoize<T>(value: T, ignoreKeys?: any) {
+  const ref = useRef<T | undefined>(undefined);
   // it can be done by using useMemo as well
   // but useRef is rather cleaner and easier
   if (!isDeepEqual(value, ref.current, ignoreKeys)) {
     ref.current = value;
   }
 
   return ref.current;
 }

方案 2 更符合编码规范中"避免使用 any 类型"和"适当使用泛型以增强类型灵活性"的要求。

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/utils/hooks/useDeepCompareEffect/index.ts around line 10, the declaration
const ref = useRef(undefined) lets TypeScript infer MutableRefObject<undefined>,
causing downstream types to be wrong; fix by adding explicit generics: make the
hook generic (e.g. function useDeepCompareEffect<T = any>(value: T, ...)) and
change the ref to useRef<T | undefined>(undefined) (or useRef<T>(undefined as
unknown as T) if necessary) so ref.current can accept the incoming value and the
return type is correctly inferred; update any related type annotations to use
the generic parameter instead of any.

Comment on lines +1109 to +1111
const saveRefsMap = useRef(
new Map<React.Key, React.RefObject<SaveEditableActionRef<any> | null>>(),
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's read the relevant section of the file to see the context
wc -l src/utils/useEditableArray/index.tsx

Repository: ant-design/pro-components

Length of output: 110


🏁 Script executed:

# Read lines around 1109-1111 to see the saveRefsMap definition
sed -n '1100,1120p' src/utils/useEditableArray/index.tsx

Repository: ant-design/pro-components

Length of output: 648


🏁 Script executed:

# Find all usages of saveRefsMap to check how it's being used
rg -n "saveRefsMap" src/utils/useEditableArray/index.tsx

Repository: ant-design/pro-components

Length of output: 422


🏁 Script executed:

# Check line 1158 and surrounding context to see the saveRef?.current usage
sed -n '1150,1170p' src/utils/useEditableArray/index.tsx

Repository: ant-design/pro-components

Length of output: 456


🏁 Script executed:

# Find the SaveEditableActionRef type definition
rg -n "SaveEditableActionRef" src/utils/useEditableArray/index.tsx | head -20

Repository: ant-design/pro-components

Length of output: 427


🏁 Script executed:

# Find the getSaveRef function definition
rg -n "getSaveRef" src/utils/useEditableArray/index.tsx

Repository: ant-design/pro-components

Length of output: 187


🏁 Script executed:

# Check the context around lines 1130-1131 where saveRefsMap.current.get is used
sed -n '1125,1145p' src/utils/useEditableArray/index.tsx

Repository: ant-design/pro-components

Length of output: 757


🏁 Script executed:

# Check the SaveEditableActionRef type definition at line 486
sed -n '486,510p' src/utils/useEditableArray/index.tsx

Repository: ant-design/pro-components

Length of output: 509


🏁 Script executed:

# Check where saveRefsMap.current.set is called (lines 1420, 1426) to see what values are stored
sed -n '1415,1435p' src/utils/useEditableArray/index.tsx

Repository: ant-design/pro-components

Length of output: 744


🏁 Script executed:

# Check if there's any explicit null assignment to saveRefsMap
rg -n "saveRefsMap.*null" src/utils/useEditableArray/index.tsx

Repository: ant-design/pro-components

Length of output: 51


🏁 Script executed:

# Get more context around line 1157 to see how saveRef is used after getSaveRef
sed -n '1155,1175p' src/utils/useEditableArray/index.tsx

Repository: ant-design/pro-components

Length of output: 497


🏁 Script executed:

# Search for all references to the result of getSaveRef and how it's used
rg -n "getSaveRef\(" src/utils/useEditableArray/index.tsx -A5

Repository: ant-design/pro-components

Length of output: 241


🏁 Script executed:

# Check the defaultActionRender function to understand what renderResult.saveRef is
rg -n "defaultActionRender" src/utils/useEditableArray/index.tsx -B5 -A10 | head -40

Repository: ant-design/pro-components

Length of output: 1134


🏁 Script executed:

# Let's check the defaultActionRender return type to understand what renderResult.saveRef is
sed -n '604,630p' src/utils/useEditableArray/index.tsx

Repository: ant-design/pro-components

Length of output: 832


🏁 Script executed:

# Let's verify what createRef returns in React
rg -n "createRef" src/utils/useEditableArray/index.tsx

Repository: ant-design/pro-components

Length of output: 145


🏁 Script executed:

# Check if there's a type definition for the return value of defaultActionRender
rg -n "return \{" src/utils/useEditableArray/index.tsx | grep -A20 "defaultActionRender"

Repository: ant-design/pro-components

Length of output: 51


🏁 Script executed:

# Check if there are any explicit null assignments or patterns in the whole file
rg -n "saveRefsMap.*=.*null|null.*saveRefsMap" src/utils/useEditableArray/index.tsx

Repository: ant-design/pro-components

Length of output: 51


🏁 Script executed:

# Let's check the import statements to understand React.RefObject better
sed -n '1,30p' src/utils/useEditableArray/index.tsx

Repository: ant-design/pro-components

Length of output: 1117


🏁 Script executed:

# Check all Map operations on saveRefsMap to see if null is ever intentionally stored
rg -n "\.set\(" src/utils/useEditableArray/index.tsx | grep -A2 -B2 "saveRefsMap"

Repository: ant-design/pro-components

Length of output: 281


🏁 Script executed:

# Let's check the complete context of how getSaveRef result is used elsewhere
rg -n "const.*saveRef.*getSaveRef\|getSaveRef.*current" src/utils/useEditableArray/index.tsx -A3

Repository: ant-design/pro-components

Length of output: 51


🏁 Script executed:

# Check if there are any other usages we might have missed
rg -n "saveRefsMap.current" src/utils/useEditableArray/index.tsx -B2 -A2

Repository: ant-design/pro-components

Length of output: 902


saveRefsMap 的类型注解中包含不必要的 | null

Map 的类型定义为 React.RefObject<SaveEditableActionRef<any> | null>,但实际存储的值来自 createRef<SaveEditableActionRef<T>>(),始终返回有效的 RefObject,不会存储 null 值。

第 1158 行的 if (!saveRef?.current) 正确处理了 Map.get() 可能返回的 undefined(通过 || 操作符),但类型注解应移除 | null,改为:

Map<React.Key, React.RefObject<SaveEditableActionRef<any>>>

这样类型更精确,避免误导维护者认为会存储 null 值的 RefObject。

🤖 Prompt for AI Agents
In src/utils/useEditableArray/index.tsx around lines 1109 to 1111, the Map type
for saveRefsMap currently uses React.RefObject<SaveEditableActionRef<any> |
null> which incorrectly suggests stored RefObjects may be null; change the
generic to React.RefObject<SaveEditableActionRef<any>> so the Map is typed as
Map<React.Key, React.RefObject<SaveEditableActionRef<any>>> to reflect that
createRef always returns a non-null RefObject and keep the runtime check (if
(!saveRef?.current)) for undefined Map.get() results.

@zzjiaxiang zzjiaxiang marked this pull request as draft January 4, 2026 06:01
- Changed type references from `RefObject` to `React.Ref` for better compatibility in various components including forms, lists, and layouts.
- Updated the `captchaRef` in the demo to use a specific type for improved type safety.
- Enhanced documentation for `actionRef` across multiple components to reflect the updated type definitions.

These changes improve type safety and maintainability across the codebase.
This reverts commit 9528f10.
@chenshuai2144
Copy link
Contributor

冲突有点多了

- Bump versions for several packages including '@ant-design/cssinjs', '@rc-component/form', and '@umijs/utils'.
- Remove outdated dependencies and add new ones such as '@rc-component/resize-observer' and '@rc-component/steps'.
- Update peer dependencies for various components to ensure compatibility with the latest versions.
- Clean up unnecessary entries and ensure consistency across the lock file.
@zzjiaxiang
Copy link
Contributor Author

改的都是类型,运行了下测试,发现很多都挂了 😂

- Updated multiple test files to replace the useRef hook with createRef for formRef, enhancing consistency in reference handling across ProForm and ModalForm tests.
- This change improves clarity and aligns with best practices for creating refs in React.
@zzjiaxiang zzjiaxiang marked this pull request as ready for review January 15, 2026 12:18
@coderabbitai coderabbitai bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Jan 15, 2026
@dosubot dosubot bot added size:M This PR changes 30-99 lines, ignoring generated files. and removed size:M This PR changes 30-99 lines, ignoring generated files. size:XXL This PR changes 1000+ lines, ignoring generated files. labels Jan 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file form list size:M This PR changes 30-99 lines, ignoring generated files. table

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants