Skip to content

Commit f3806bd

Browse files
committed
type: React.Key => SafeKey
1 parent b01e960 commit f3806bd

13 files changed

+106
-110
lines changed

.husky/pre-commit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
lint-staged

package.json

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,49 +34,54 @@
3434
"compile": "father build",
3535
"lint": "eslint src/ examples/ --ext .tsx,.ts,.jsx,.js",
3636
"now-build": "npm run build",
37-
"prepare": "dumi setup",
37+
"prepare": "husky",
3838
"prepublishOnly": "npm run compile && np --yolo --no-publish --any-branch",
3939
"prettier": "prettier '{src,tests}/**/*.{ts,tsx}' 'tests/**/*.js' --write",
4040
"start": "dumi dev",
4141
"test": "rc-test"
4242
},
43+
"lint-staged": {
44+
"*": "prettier --write --ignore-unknown"
45+
},
4346
"dependencies": {
4447
"@babel/runtime": "^7.25.7",
45-
"classnames": "2.x",
46-
"rc-select": "~14.15.0",
47-
"rc-tree": "~5.9.0",
48+
"classnames": "^2.5.1",
49+
"rc-select": "~14.15.2",
50+
"rc-tree": "~5.10.0",
4851
"rc-util": "^5.43.0"
4952
},
5053
"devDependencies": {
51-
"@rc-component/father-plugin": "^1.0.0",
52-
"@rc-component/trigger": "^1.5.0",
53-
"@testing-library/react": "^12.0.0",
54-
"@types/jest": "^29.5.12",
54+
"@rc-component/father-plugin": "^1.1.0",
55+
"@rc-component/trigger": "^1.18.3",
56+
"@testing-library/react": "^12.1.5",
57+
"@types/jest": "^29.5.13",
5558
"@types/node": "^22.7.5",
5659
"@types/react": "^18.3.11",
57-
"@types/react-dom": "^18.2.19",
58-
"@types/warning": "^3.0.0",
60+
"@types/react-dom": "^18.3.1",
61+
"@types/warning": "^3.0.3",
5962
"@umijs/fabric": "^4.0.1",
63+
"cheerio": "1.0.0-rc.12",
6064
"cross-env": "^7.0.3",
6165
"dumi": "^2.4.12",
6266
"enzyme": "^3.11.0",
6367
"enzyme-adapter-react-16": "^1.15.8",
6468
"enzyme-to-json": "^3.6.2",
65-
"eslint": "^8.56.0",
66-
"eslint-plugin-jest": "^27.6.0",
69+
"eslint": "^8.57.1",
70+
"eslint-plugin-jest": "^27.9.0",
6771
"eslint-plugin-unicorn": "^56.0.0",
6872
"father": "^4.5.0",
6973
"glob": "^11.0.0",
74+
"husky": "^9.1.6",
75+
"lint-staged": "^15.2.10",
7076
"np": "^10.0.7",
7177
"prettier": "^3.3.3",
7278
"rc-dialog": "^9.6.0",
7379
"rc-field-form": "^2.4.0",
7480
"rc-test": "^7.1.0",
7581
"rc-virtual-list": "^3.14.8",
76-
"react": "16.x",
77-
"react-dom": "16.x",
78-
"typescript": "^5.6.3",
79-
"cheerio": "1.0.0-rc.12"
82+
"react": "^18.3.1",
83+
"react-dom": "^18.3.1",
84+
"typescript": "^5.6.3"
8085
},
8186
"peerDependencies": {
8287
"react": "*",

src/LegacyContext.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
import * as React from 'react';
22
import type { DataEntity, IconType } from 'rc-tree/lib/interface';
3-
import type { Key, LegacyDataNode, RawValueType } from './interface';
3+
import type { LegacyDataNode, SafeKey } from './interface';
44

55
interface LegacyContextProps {
66
checkable: boolean | React.ReactNode;
7-
checkedKeys: Key[];
8-
halfCheckedKeys: Key[];
9-
treeExpandedKeys: Key[];
10-
treeDefaultExpandedKeys: Key[];
11-
onTreeExpand: (keys: Key[]) => void;
7+
checkedKeys: SafeKey[];
8+
halfCheckedKeys: SafeKey[];
9+
treeExpandedKeys: SafeKey[];
10+
treeDefaultExpandedKeys: SafeKey[];
11+
onTreeExpand: (keys: SafeKey[]) => void;
1212
treeDefaultExpandAll: boolean;
1313
treeIcon: IconType;
1414
showTreeIcon: boolean;
1515
switcherIcon: IconType;
1616
treeLine: boolean;
1717
treeNodeFilterProp: string;
18-
treeLoadedKeys: Key[];
18+
treeLoadedKeys: SafeKey[];
1919
treeMotion: any;
2020
loadData: (treeNode: LegacyDataNode) => Promise<unknown>;
21-
onTreeLoad: (loadedKeys: Key[]) => void;
21+
onTreeLoad: (loadedKeys: SafeKey[]) => void;
2222

23-
keyEntities: Record<RawValueType, DataEntity<any>>;
23+
keyEntities: Record<SafeKey, DataEntity<any>>;
2424
}
2525

2626
const LegacySelectContext = React.createContext<LegacyContextProps>(null);

src/OptionList.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import useMemo from 'rc-util/lib/hooks/useMemo';
88
import * as React from 'react';
99
import LegacyContext from './LegacyContext';
1010
import TreeSelectContext from './TreeSelectContext';
11-
import type { Key, TreeDataNode } from './interface';
11+
import type { SafeKey, TreeDataNode } from './interface';
1212
import { getAllKeys, isCheckDisabled } from './utils/valueUtil';
1313

1414
const HIDDEN_STYLE = {
@@ -23,7 +23,7 @@ const HIDDEN_STYLE = {
2323
};
2424

2525
interface TreeEventInfo {
26-
node: { key: Key };
26+
node: { key: SafeKey };
2727
selected?: boolean;
2828
checked?: boolean;
2929
}
@@ -77,7 +77,7 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
7777
);
7878

7979
// ========================== Active ==========================
80-
const [activeKey, setActiveKey] = React.useState<Key>(null);
80+
const [activeKey, setActiveKey] = React.useState<SafeKey>(null);
8181
const activeEntity = keyEntities[activeKey];
8282

8383
// ========================== Values ==========================
@@ -112,8 +112,8 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
112112
};
113113

114114
// =========================== Keys ===========================
115-
const [expandedKeys, setExpandedKeys] = React.useState<Key[]>(treeDefaultExpandedKeys);
116-
const [searchExpandedKeys, setSearchExpandedKeys] = React.useState<Key[]>(null);
115+
const [expandedKeys, setExpandedKeys] = React.useState<SafeKey[]>(treeDefaultExpandedKeys);
116+
const [searchExpandedKeys, setSearchExpandedKeys] = React.useState<SafeKey[]>(null);
117117

118118
const mergedExpandedKeys = React.useMemo(() => {
119119
if (treeExpandedKeys) {
@@ -129,7 +129,7 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
129129
// eslint-disable-next-line react-hooks/exhaustive-deps
130130
}, [searchValue]);
131131

132-
const onInternalExpand = (keys: Key[]) => {
132+
const onInternalExpand = (keys: SafeKey[]) => {
133133
setExpandedKeys(keys);
134134
setSearchExpandedKeys(keys);
135135

@@ -143,7 +143,7 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
143143
event.preventDefault();
144144
};
145145

146-
const onInternalSelect = (__: React.Key[], info: TreeEventInfo) => {
146+
const onInternalSelect = (__: SafeKey[], info: TreeEventInfo) => {
147147
const { node } = info;
148148

149149
if (checkable && isCheckDisabled(node)) {

src/TreeNode.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
/* istanbul ignore file */
22
import type * as React from 'react';
3-
import type { DataNode, Key } from './interface';
3+
import type { DataNode, SafeKey } from './interface';
44

55
export interface TreeNodeProps extends Omit<DataNode, 'children'> {
6-
value: Key;
6+
value: SafeKey;
77
children?: React.ReactNode;
88
}
99

src/TreeSelect.tsx

Lines changed: 26 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,9 @@ import type { CheckedStrategy } from './utils/strategyUtil';
2828
import { formatStrategyValues, SHOW_ALL, SHOW_CHILD, SHOW_PARENT } from './utils/strategyUtil';
2929
import { fillFieldNames, isNil, toArray } from './utils/valueUtil';
3030
import warningProps from './utils/warningPropsUtil';
31+
import type { LabeledValueType, SafeKey, SelectSource, DefaultValueType } from './interface';
3132

32-
export type OnInternalSelect = (value: RawValueType, info: { selected: boolean }) => void;
33-
34-
export type RawValueType = string | number;
35-
36-
export interface LabeledValueType {
37-
key?: React.Key;
38-
value?: RawValueType;
39-
label?: React.ReactNode;
40-
/** Only works on `treeCheckStrictly` */
41-
halfChecked?: boolean;
42-
}
43-
44-
export type SelectSource = 'option' | 'selection' | 'input' | 'clear';
45-
46-
export type DraftValueType = RawValueType | LabeledValueType | (RawValueType | LabeledValueType)[];
33+
export type OnInternalSelect = (value: SafeKey, info: { selected: boolean }) => void;
4734

4835
/** @deprecated This is only used for legacy compatible. Not works on new code. */
4936
export interface LegacyCheckedNode {
@@ -55,7 +42,7 @@ export interface LegacyCheckedNode {
5542
export interface ChangeEventExtra {
5643
/** @deprecated Please save prev value by control logic instead */
5744
preValue: LabeledValueType[];
58-
triggerValue: RawValueType;
45+
triggerValue: SafeKey;
5946
/** @deprecated Use `onSelect` or `onDeselect` instead. */
6047
selected?: boolean;
6148
/** @deprecated Use `onSelect` or `onDeselect` instead. */
@@ -79,9 +66,9 @@ export interface InternalFieldName extends Omit<FieldNames, 'label'> {
7966
}
8067

8168
export interface SimpleModeConfig {
82-
id?: React.Key;
83-
pId?: React.Key;
84-
rootPId?: React.Key;
69+
id?: SafeKey;
70+
pId?: SafeKey;
71+
rootPId?: SafeKey;
8572
}
8673

8774
export interface BaseOptionType {
@@ -93,10 +80,10 @@ export interface BaseOptionType {
9380
}
9481

9582
export interface DefaultOptionType extends BaseOptionType {
96-
value?: RawValueType;
83+
value?: SafeKey;
9784
title?: React.ReactNode;
9885
label?: React.ReactNode;
99-
key?: React.Key;
86+
key?: SafeKey;
10087
children?: DefaultOptionType[];
10188
}
10289

@@ -145,14 +132,14 @@ export interface TreeSelectProps<
145132
treeData?: OptionType[];
146133
treeDataSimpleMode?: boolean | SimpleModeConfig;
147134
loadData?: (dataNode: LegacyDataNode) => Promise<unknown>;
148-
treeLoadedKeys?: React.Key[];
149-
onTreeLoad?: (loadedKeys: React.Key[]) => void;
135+
treeLoadedKeys?: SafeKey[];
136+
onTreeLoad?: (loadedKeys: SafeKey[]) => void;
150137

151138
// >>> Expanded
152139
treeDefaultExpandAll?: boolean;
153-
treeExpandedKeys?: React.Key[];
154-
treeDefaultExpandedKeys?: React.Key[];
155-
onTreeExpand?: (expandedKeys: React.Key[]) => void;
140+
treeExpandedKeys?: SafeKey[];
141+
treeDefaultExpandedKeys?: SafeKey[];
142+
onTreeExpand?: (expandedKeys: SafeKey[]) => void;
156143
treeExpandAction?: ExpandAction;
157144

158145
// >>> Options
@@ -171,7 +158,7 @@ export interface TreeSelectProps<
171158
treeMotion?: any;
172159
}
173160

174-
function isRawValue(value: RawValueType | LabeledValueType): value is RawValueType {
161+
function isRawValue(value: SafeKey | LabeledValueType): value is SafeKey {
175162
return !value || typeof value !== 'object';
176163
}
177164

@@ -295,7 +282,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
295282

296283
/** Get `missingRawValues` which not exist in the tree yet */
297284
const splitRawValues = React.useCallback(
298-
(newRawValues: RawValueType[]) => {
285+
(newRawValues: SafeKey[]) => {
299286
const missingRawValues = [];
300287
const existRawValues = [];
301288

@@ -343,7 +330,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
343330
);
344331

345332
// ========================= Wrap Value =========================
346-
const toLabeledValues = React.useCallback((draftValues: DraftValueType) => {
333+
const toLabeledValues = React.useCallback((draftValues: DefaultValueType) => {
347334
const values = toArray(draftValues);
348335

349336
return values.map(val => {
@@ -355,7 +342,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
355342
}, []);
356343

357344
const convert2LabelValues = React.useCallback(
358-
(draftValues: DraftValueType) => {
345+
(draftValues: DefaultValueType) => {
359346
const values = toLabeledValues(draftValues);
360347

361348
return values.map(item => {
@@ -368,7 +355,9 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
368355

369356
// Fill missing label & status
370357
if (entity) {
371-
rawLabel = treeTitleRender ? treeTitleRender(entity.node) : rawLabel ?? getLabel(entity.node);
358+
rawLabel = treeTitleRender
359+
? treeTitleRender(entity.node)
360+
: (rawLabel ?? getLabel(entity.node));
372361
rawDisabled = entity.node.disabled;
373362
} else if (rawLabel === undefined) {
374363
// We try to find in current `labelInValue` value
@@ -475,8 +464,8 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
475464
// =========================== Change ===========================
476465
const triggerChange = useRefFunc(
477466
(
478-
newRawValues: RawValueType[],
479-
extra: { triggerValue?: RawValueType; selected?: boolean },
467+
newRawValues: SafeKey[],
468+
extra: { triggerValue?: SafeKey; selected?: boolean },
480469
source: SelectSource,
481470
) => {
482471
const labeledValues = convert2LabelValues(newRawValues);
@@ -489,7 +478,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
489478

490479
// Generate rest parameters is costly, so only do it when necessary
491480
if (onChange) {
492-
let eventValues: RawValueType[] = newRawValues;
481+
let eventValues: SafeKey[] = newRawValues;
493482
if (treeConduction) {
494483
const formattedKeyList = formatStrategyValues(
495484
newRawValues,
@@ -508,7 +497,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
508497
selected: undefined,
509498
};
510499

511-
let returnRawValues: (LabeledValueType | RawValueType)[] = eventValues;
500+
let returnRawValues: (LabeledValueType | SafeKey)[] = eventValues;
512501

513502
// We need fill half check back
514503
if (treeCheckStrictly) {
@@ -563,7 +552,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
563552
// ========================== Options ===========================
564553
/** Trigger by option list */
565554
const onOptionSelect = React.useCallback(
566-
(selectedKey: React.Key, { selected, source }: { selected: boolean; source: SelectSource }) => {
555+
(selectedKey: SafeKey, { selected, source }: { selected: boolean; source: SelectSource }) => {
567556
const entity = keyEntities[selectedKey];
568557
const node = entity?.node;
569558
const selectedValue = node?.[mergedFieldNames.value] ?? selectedKey;
@@ -584,7 +573,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
584573
const keyList = existRawValues.map(val => valueEntities.get(val).key);
585574

586575
// Conduction by selected or not
587-
let checkedKeys: React.Key[];
576+
let checkedKeys: SafeKey[];
588577
if (selected) {
589578
({ checkedKeys } = conductCheck(keyList, true, keyEntities));
590579
} else {

src/hooks/useCache.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import * as React from 'react';
2-
import type { LabeledValueType, RawValueType } from '../TreeSelect';
2+
import type { LabeledValueType, SafeKey } from '../interface';
33

44
/**
55
* This function will try to call requestIdleCallback if available to save performance.
66
* No need `getLabel` here since already fetch on `rawLabeledValue`.
77
*/
88
export default (values: LabeledValueType[]): [LabeledValueType[]] => {
99
const cacheRef = React.useRef({
10-
valueLabels: new Map<RawValueType, React.ReactNode>(),
10+
valueLabels: new Map<SafeKey, React.ReactNode>(),
1111
});
1212

1313
return React.useMemo(() => {
1414
const { valueLabels } = cacheRef.current;
15-
const valueLabelsCache = new Map<RawValueType, React.ReactNode>();
15+
const valueLabelsCache = new Map<SafeKey, React.ReactNode>();
1616

1717
const filledValues = values.map(item => {
1818
const { value } = item;

0 commit comments

Comments
 (0)