From 775b119223a77a088cff9843964544c5e3ed6929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BA=A2?= Date: Wed, 27 Sep 2023 16:36:41 +0800 Subject: [PATCH] type: fix type errors of React.Key (#45018) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update index.zh-CN.md Signed-off-by: 红 * Revert "Update index.zh-CN.md" This reverts commit cfcce5dd560180c0eccdda1ca01922f59e1770af. * docs: format ref: https://github.com/ant-design/ant-design/pull/37144/files#diff-0bdf37a1fc0ec124fb3aa391932eaa134bd1de8c6f766f5e4082edbc30ce6c42 * chore: update snapshots * type: fix type errors of React.Key ref: https://github.com/ant-design/ant-design/pull/44938 Co-authored-by: afc163 * test: fix test logic (cherry picked from commit 6a349f697c5b16fd6b188f22832463b41de8b3c1) * deps: bump rc-field-form@1.38.2 ref: https://github.com/ant-design/ant-design/pull/45018#issuecomment-1732341463 * type: fix FormItem Key * chore: fix lint * chore: fix lint --------- Signed-off-by: 红 Co-authored-by: afc163 Co-authored-by: 二货机器人 --- .../__snapshots__/components.test.tsx.snap | 1 + components/form/FormItem/index.tsx | 4 +- .../__snapshots__/demo-extend.test.ts.snap | 1 + .../__tests__/__snapshots__/demo.test.ts.snap | 1 + .../__snapshots__/index.test.tsx.snap | 1 + components/form/__tests__/index.test.tsx | 9 ++-- .../table/__tests__/Table.filter.test.tsx | 2 +- components/table/demo/custom-filter-panel.md | 2 +- .../table/hooks/useFilter/FilterDropdown.tsx | 41 +++++++++++-------- components/table/hooks/useFilter/index.tsx | 16 +++++--- components/table/interface.tsx | 8 ++-- components/transfer/demo/tree-transfer.md | 2 +- components/tree/index.zh-CN.md | 2 +- package.json | 2 +- 14 files changed, 55 insertions(+), 37 deletions(-) diff --git a/components/config-provider/__tests__/__snapshots__/components.test.tsx.snap b/components/config-provider/__tests__/__snapshots__/components.test.tsx.snap index 978e55274583..03aa210aecba 100644 --- a/components/config-provider/__tests__/__snapshots__/components.test.tsx.snap +++ b/components/config-provider/__tests__/__snapshots__/components.test.tsx.snap @@ -42717,6 +42717,7 @@ exports[`ConfigProvider components Upload configProvider componentDisabled 1`] = > diff --git a/components/form/FormItem/index.tsx b/components/form/FormItem/index.tsx index 0cf8f17dd194..f57c09d3516e 100644 --- a/components/form/FormItem/index.tsx +++ b/components/form/FormItem/index.tsx @@ -1,7 +1,7 @@ import type { FormInstance } from 'rc-field-form'; import { Field, FieldContext, ListContext } from 'rc-field-form'; import type { FieldProps } from 'rc-field-form/lib/Field'; -import type { Meta, NamePath } from 'rc-field-form/lib/interface'; +import type { Meta, NamePath, InternalNamePath } from 'rc-field-form/lib/interface'; import useState from 'rc-util/lib/hooks/useState'; import { supportRef } from 'rc-util/lib/ref'; import * as React from 'react'; @@ -120,7 +120,7 @@ function InternalFormItem(props: FormItemProps): React.Rea // ========================= MISC ========================= // Get `noStyle` required info const listContext = React.useContext(ListContext); - const fieldKeyPathRef = React.useRef(); + const fieldKeyPathRef = React.useRef(); // ======================== Errors ======================== // >>>>> Collect sub field errors diff --git a/components/form/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/form/__tests__/__snapshots__/demo-extend.test.ts.snap index 9db6e3f363b5..d87c5060b794 100644 --- a/components/form/__tests__/__snapshots__/demo-extend.test.ts.snap +++ b/components/form/__tests__/__snapshots__/demo-extend.test.ts.snap @@ -5071,6 +5071,7 @@ Array [ > diff --git a/components/form/__tests__/__snapshots__/demo.test.ts.snap b/components/form/__tests__/__snapshots__/demo.test.ts.snap index 9fc8e69a86fb..04a2c6020b18 100644 --- a/components/form/__tests__/__snapshots__/demo.test.ts.snap +++ b/components/form/__tests__/__snapshots__/demo.test.ts.snap @@ -2554,6 +2554,7 @@ Array [ > diff --git a/components/form/__tests__/__snapshots__/index.test.tsx.snap b/components/form/__tests__/__snapshots__/index.test.tsx.snap index b72605a3cc4c..549ad2459d9e 100644 --- a/components/form/__tests__/__snapshots__/index.test.tsx.snap +++ b/components/form/__tests__/__snapshots__/index.test.tsx.snap @@ -929,6 +929,7 @@ exports[`Form form should support disabled 1`] = ` > diff --git a/components/form/__tests__/index.test.tsx b/components/form/__tests__/index.test.tsx index 55ac755b8801..a70229ed1d26 100644 --- a/components/form/__tests__/index.test.tsx +++ b/components/form/__tests__/index.test.tsx @@ -1558,20 +1558,21 @@ describe('Form', () => { const App2 = () =>
{renderComps()}
; const wrapper2 = render(); - // 时间范围组件中会有两个 input 框,因此虽然上述只有 18 个组件,但,实际有 19 个 带有 disabled 属性的表单组件 - expect(wrapper2.container.querySelectorAll('[disabled]').length).toBe(19); + // 时间范围组件中会有两个 input 框,Upload 为叠加 + // 因此虽然上述只有 18 个组件,但实际有 20 个 带有 disabled 属性的表单组件 + expect(wrapper2.container.querySelectorAll('[disabled]').length).toBe(20); const App3 = () =>
{renderComps(true)}
; const wrapper3 = render(); - expect(wrapper3.container.querySelectorAll('[disabled]').length).toBe(19); + expect(wrapper3.container.querySelectorAll('[disabled]').length).toBe(20); const App4 = () =>
{renderComps(true)}
; const wrapper4 = render(); - expect(wrapper4.container.querySelectorAll('[disabled]').length).toBe(19); + expect(wrapper4.container.querySelectorAll('[disabled]').length).toBe(20); const App5 = () =>
{renderComps()}
; diff --git a/components/table/__tests__/Table.filter.test.tsx b/components/table/__tests__/Table.filter.test.tsx index f39a701bc9a8..d8eee4b032b9 100644 --- a/components/table/__tests__/Table.filter.test.tsx +++ b/components/table/__tests__/Table.filter.test.tsx @@ -968,7 +968,7 @@ describe('Table.filter', () => { filterDropdown: ({ setSelectedKeys, selectedKeys, confirm }) => (
{ setSelectedKeys(e.target.value ? [e.target.value] : []); }} diff --git a/components/table/demo/custom-filter-panel.md b/components/table/demo/custom-filter-panel.md index be69bd5f2bdd..cf2b72530ea0 100644 --- a/components/table/demo/custom-filter-panel.md +++ b/components/table/demo/custom-filter-panel.md @@ -88,7 +88,7 @@ const App: React.FC = () => { setSelectedKeys(e.target.value ? [e.target.value] : [])} onPressEnter={() => handleSearch(selectedKeys as string[], confirm, dataIndex)} style={{ marginBottom: 8, display: 'block' }} diff --git a/components/table/hooks/useFilter/FilterDropdown.tsx b/components/table/hooks/useFilter/FilterDropdown.tsx index 23a734358a48..567a566ef390 100644 --- a/components/table/hooks/useFilter/FilterDropdown.tsx +++ b/components/table/hooks/useFilter/FilterDropdown.tsx @@ -21,6 +21,7 @@ import useSyncState from '../../../_util/hooks/useSyncState'; import type { ColumnFilterItem, ColumnType, + FilterKey, FilterSearchType, GetPopupContainer, Key, @@ -29,7 +30,7 @@ import type { import FilterSearch from './FilterSearch'; import FilterDropdownMenuWrapper from './FilterWrapper'; -type FilterTreeDataNode = FieldDataNode<{ title: React.ReactNode; key: React.Key }>; +type FilterTreeDataNode = FieldDataNode<{ title: React.ReactNode; key: string }>; interface FilterRestProps { confirm?: Boolean; @@ -121,6 +122,10 @@ export interface FilterDropdownProps { filterResetToDefaultFilteredValue?: boolean; } +function wrapStringListType(keys?: FilterKey) { + return (keys as string[]) || []; +} + function FilterDropdown(props: FilterDropdownProps) { const { tablePrefixCls, @@ -166,20 +171,22 @@ function FilterDropdown(props: FilterDropdownProps) { } // ===================== Select Keys ===================== const propFilteredKeys = filterState?.filteredKeys; - const [getFilteredKeysSync, setFilteredKeysSync] = useSyncState(propFilteredKeys || []); + const [getFilteredKeysSync, setFilteredKeysSync] = useSyncState( + wrapStringListType(propFilteredKeys), + ); - const onSelectKeys = ({ selectedKeys }: { selectedKeys: Key[] }) => { + const onSelectKeys = ({ selectedKeys }: { selectedKeys: string[] }) => { setFilteredKeysSync(selectedKeys); }; const onCheck = ( - keys: Key[], + keys: string[], { node, checked }: { node: EventDataNode; checked: boolean }, ) => { if (!filterMultiple) { onSelectKeys({ selectedKeys: checked && node.key ? [node.key] : [] }); } else { - onSelectKeys({ selectedKeys: keys as Key[] }); + onSelectKeys({ selectedKeys: keys }); } }; @@ -187,7 +194,7 @@ function FilterDropdown(props: FilterDropdownProps) { if (!visible) { return; } - onSelectKeys({ selectedKeys: propFilteredKeys || [] }); + onSelectKeys({ selectedKeys: wrapStringListType(propFilteredKeys) }); }, [propFilteredKeys]); // ====================== Open Keys ====================== @@ -210,7 +217,7 @@ function FilterDropdown(props: FilterDropdownProps) { }, [visible]); // ======================= Submit ======================== - const internalTriggerFilter = (keys: Key[] | undefined | null) => { + const internalTriggerFilter = (keys: string[] | undefined | null) => { const mergedKeys = keys && keys.length ? keys : null; if (mergedKeys === null && (!filterState || !filterState.filteredKeys)) { return null; @@ -245,7 +252,7 @@ function FilterDropdown(props: FilterDropdownProps) { setSearchValue(''); if (filterResetToDefaultFilteredValue) { - setFilteredKeysSync((defaultFilteredValue || []).map(key => String(key))); + setFilteredKeysSync((defaultFilteredValue || []).map((key) => String(key))); } else { setFilteredKeysSync([]); } @@ -261,7 +268,7 @@ function FilterDropdown(props: FilterDropdownProps) { const onVisibleChange = (newVisible: boolean) => { if (newVisible && propFilteredKeys !== undefined) { // Sync filteredKeys on appear in controlled mode (propFilteredKeys !== undefiend) - setFilteredKeysSync(propFilteredKeys || []); + setFilteredKeysSync(wrapStringListType(propFilteredKeys)); } triggerVisible(newVisible); @@ -279,7 +286,7 @@ function FilterDropdown(props: FilterDropdownProps) { const onCheckAll = (e: CheckboxChangeEvent) => { if (e.target.checked) { - const allFilterKeys = flattenKeys(column?.filters).map(key => String(key)); + const allFilterKeys = flattenKeys(column?.filters).map((key) => String(key)); setFilteredKeysSync(allFilterKeys); } else { setFilteredKeysSync([]); @@ -291,7 +298,7 @@ function FilterDropdown(props: FilterDropdownProps) { const key = String(filter.value); const item: FilterTreeDataNode = { title: filter.text, - key: filter.value !== undefined ? key : index, + key: filter.value !== undefined ? key : String(index), }; if (filter.children) { item.children = getTreeData({ filters: filter.children }); @@ -302,7 +309,7 @@ function FilterDropdown(props: FilterDropdownProps) { ...node, text: node.title, value: node.key, - children: node.children?.map(item => getFilterData(item)) || [], + children: node.children?.map((item) => getFilterData(item)) || [], }); let dropdownContent: React.ReactNode; @@ -310,7 +317,7 @@ function FilterDropdown(props: FilterDropdownProps) { if (typeof column.filterDropdown === 'function') { dropdownContent = column.filterDropdown({ prefixCls: `${dropdownPrefixCls}-custom`, - setSelectedKeys: (selectedKeys: Key[]) => onSelectKeys({ selectedKeys }), + setSelectedKeys: (selectedKeys: string[]) => onSelectKeys({ selectedKeys }), selectedKeys: getFilteredKeysSync(), confirm: doFilter, clearFilters: onReset, @@ -323,7 +330,7 @@ function FilterDropdown(props: FilterDropdownProps) { } else if (column.filterDropdown) { dropdownContent = column.filterDropdown; } else { - const selectedKeys = (getFilteredKeysSync() || []) as any; + const selectedKeys = getFilteredKeysSync() || []; const getFilterComponent = () => { if ((column.filters || []).length === 0) { return ( @@ -380,7 +387,7 @@ function FilterDropdown(props: FilterDropdownProps) { defaultExpandAll filterTreeNode={ searchValue.trim() - ? node => { + ? (node) => { if (typeof filterSearch === 'function') { return filterSearch(searchValue, getFilterData(node)); } @@ -429,7 +436,7 @@ function FilterDropdown(props: FilterDropdownProps) { const getResetDisabled = () => { if (filterResetToDefaultFilteredValue) { return isEqual( - (defaultFilteredValue || []).map(key => String(key)), + (defaultFilteredValue || []).map((key) => String(key)), selectedKeys, ); } @@ -491,7 +498,7 @@ function FilterDropdown(props: FilterDropdownProps) { className={classNames(`${prefixCls}-trigger`, { active: filtered, })} - onClick={e => { + onClick={(e) => { e.stopPropagation(); }} > diff --git a/components/table/hooks/useFilter/index.tsx b/components/table/hooks/useFilter/index.tsx index 8fb7e55659bd..11b56fe00d45 100644 --- a/components/table/hooks/useFilter/index.tsx +++ b/components/table/hooks/useFilter/index.tsx @@ -9,6 +9,7 @@ import type { FilterValue, GetPopupContainer, Key, + SafeKey, TableLocale, TransformColumns, } from '../../interface'; @@ -144,14 +145,17 @@ function generateFilterInfo(filterStates: FilterState[]) const currentFilters: Record = {}; filterStates.forEach(({ key, filteredKeys, column }) => { + const keyAsString = key as SafeKey; const { filters, filterDropdown } = column; if (filterDropdown) { - currentFilters[key] = filteredKeys || null; + currentFilters[keyAsString] = filteredKeys || null; } else if (Array.isArray(filteredKeys)) { const keys = flattenKeys(filters); - currentFilters[key] = keys.filter(originKey => filteredKeys.includes(String(originKey))); + currentFilters[keyAsString] = keys.filter((originKey) => + filteredKeys.includes(String(originKey)), + ); } else { - currentFilters[key] = null; + currentFilters[keyAsString] = null; } }); @@ -168,10 +172,10 @@ export function getFilterData( filteredKeys, } = filterState; if (onFilter && filteredKeys && filteredKeys.length) { - return currentData.filter(record => - filteredKeys.some(key => { + return currentData.filter((record) => + filteredKeys.some((key) => { const keys = flattenKeys(filters); - const keyIndex = keys.findIndex(k => String(k) === String(key)); + const keyIndex = keys.findIndex((k) => String(k) === String(key)); const realKey = keyIndex !== -1 ? keys[keyIndex] : key; return onFilter(realKey, record); }), diff --git a/components/table/interface.tsx b/components/table/interface.tsx index d68a85fd8374..994a86d59ef6 100644 --- a/components/table/interface.tsx +++ b/components/table/interface.tsx @@ -17,6 +17,8 @@ export { GetRowKey, ExpandableConfig }; export type Key = React.Key; +export type SafeKey = Exclude; + export type RowSelectionType = 'checkbox' | 'radio'; export type SelectionItemSelectFn = (currentRowKeys: Key[]) => void; @@ -52,7 +54,7 @@ export type CompareFn = (a: T, b: T, sortOrder?: SortOrder) => number; export interface ColumnFilterItem { text: React.ReactNode; - value: string | number | boolean; + value: React.Key | boolean; children?: ColumnFilterItem[]; } @@ -71,7 +73,7 @@ export type ColumnTitle = | ((props: ColumnTitleProps) => React.ReactNode); export type FilterValue = (Key | boolean)[]; -export type FilterKey = Key[] | null; +export type FilterKey = (string | number)[] | null; export type FilterSearchType> = | boolean | ((input: string, record: RecordType) => boolean); @@ -121,7 +123,7 @@ export interface ColumnType extends Omit, ' filterIcon?: React.ReactNode | ((filtered: boolean) => React.ReactNode); filterMode?: 'menu' | 'tree'; filterSearch?: FilterSearchType; - onFilter?: (value: string | number | boolean, record: RecordType) => boolean; + onFilter?: (value: React.Key | boolean, record: RecordType) => boolean; /** * @deprecated `filterDropdownVisible` is deprecated which will be removed in next major version. * Please use `filterDropdownOpen` instead. diff --git a/components/transfer/demo/tree-transfer.md b/components/transfer/demo/tree-transfer.md index 69121faeb197..1fb2d5be51c2 100644 --- a/components/transfer/demo/tree-transfer.md +++ b/components/transfer/demo/tree-transfer.md @@ -26,7 +26,7 @@ interface TreeTransferProps { } // Customize Table Transfer -const isChecked = (selectedKeys: (string | number)[], eventKey: string | number) => +const isChecked = (selectedKeys: React.Key[], eventKey: React.Key) => selectedKeys.includes(eventKey); const generateTree = (treeNodes: DataNode[] = [], checkedKeys: string[] = []): DataNode[] => diff --git a/components/tree/index.zh-CN.md b/components/tree/index.zh-CN.md index cb44f7056e5f..06bd8eaec4e6 100644 --- a/components/tree/index.zh-CN.md +++ b/components/tree/index.zh-CN.md @@ -17,7 +17,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/Xh-oWqg9k/Tree.svg ### Tree props | 参数 | 说明 | 类型 | 默认值 | 版本 | -| --- | --- | --- | --- | --- | --- | +| --- | --- | --- | --- | --- | | allowDrop | 是否允许拖拽时放置在该节点 | ({ dropNode, dropPosition }) => boolean | - | | | autoExpandParent | 是否自动展开父节点 | boolean | false | | | blockNode | 是否节点占据一行 | boolean | false | | diff --git a/package.json b/package.json index 2573cdfc3380..b1fd488c397a 100644 --- a/package.json +++ b/package.json @@ -131,7 +131,7 @@ "rc-dialog": "~9.0.2", "rc-drawer": "~6.3.0", "rc-dropdown": "~4.0.1", - "rc-field-form": "~1.34.2", + "rc-field-form": "~1.38.2", "rc-image": "~5.13.0", "rc-input": "~0.1.4", "rc-input-number": "~7.3.11",