Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/PickerInput/hooks/useRangeValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,10 +283,11 @@ export default function useRangeValue<ValueType extends DateType[], DateType ext

// Trigger `onChange` if needed
if (onChange && !isSameMergedDates) {
const everyEmpty = clone.every((val) => !val);
onChange(
// Return null directly if all date are empty
isNullValue && clone.every((val) => !val) ? null : clone,
getDateTexts(clone),
isNullValue && everyEmpty ? null : clone,
everyEmpty ? null : getDateTexts(clone),
);
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

你好,这个改动将 dateString 在清空时设置为 null,这与 onChange 回调函数在 PickerPropsRangePickerProps 中的类型定义不一致,可能会导致 TypeScript 编译错误。

例如,在 RangePickerProps 中,dateStrings 的类型是 [string, string],并不接受 null

// src/PickerInput/RangePicker.tsx
export interface BaseRangePickerProps<DateType extends object> {
  // ...
  onChange?: (
    dates: NoUndefinedRangeValueType<DateType> | null,
    dateStrings: [string, string], // <--- 这里应该是 [string, string] | null
  ) => void;
  // ...
}

PickerProps (用于 SinglePicker) 中,dateString 的类型是 string | string[],同样不接受 null

// src/PickerInput/SinglePicker.tsx
export interface BasePickerProps<DateType extends object = any> {
  // ...
  onChange?: (date: DateType | DateType[], dateString: string | string[]) => void; // <--- 这里应该是 string | string[] | null
  // ...
}

虽然测试用例已经更新以适应 null 值,但 TypeScript 的类型定义也需要同步更新,以避免给库的使用者带来类型错误。

建议在 src/PickerInput/RangePicker.tsxsrc/PickerInput/SinglePicker.tsx 中更新 onChange 的类型定义,以允许 dateString / dateStringsnull

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

🧩 Analysis chain

仅在 clear(value 为 null)时将 dateStrings 置为 null,避免扩大行为面;并显式比较 null

当前实现对第二参采用 everyEmpty ? null : getDateTexts(clone),即便不是 clear 操作、但两端都为 null 的场景也会返回 dateStrings = null。这超出了本 PR 目标“当 value 为 null 时,dateString 为 null”,且与第一参的判定不一致(第一参受 isNullValue && everyEmpty 约束)。

建议:

  • 将第二参同样受 isNullValue && everyEmpty 约束,保证只有 clear 时才传 null
  • everyEmpty 判定使用 val == null 可读性更强、语义更精确。

可按如下修改:

-        const everyEmpty = clone.every((val) => !val);
+        const everyEmpty = clone.every((val) => val == null);

         onChange(
           // Return null directly if all date are empty
-          isNullValue && everyEmpty ? null : clone,
-          everyEmpty ? null : getDateTexts(clone),
+          isNullValue && everyEmpty ? null : clone,
+          isNullValue && everyEmpty ? null : getDateTexts(clone),
         );

[uggest_recommended_refactor]

为确保类型一致性,请确认 onChange 第二参数类型已允许 null(单选与范围)。可用以下脚本检索类型定义并核对是否包含 | null


🏁 Script executed:

#!/bin/bash
# 查找 RangePicker 与 Picker 的 onChange 类型定义
rg -nP -C3 '\binterface\s+RangePickerProps\b[\s\S]*?\bonChange\?\s*:\s*\(' --type ts --type tsx
rg -nP -C3 '\binterface\s+PickerProps\b[\s\S]*?\bonChange\?\s*:\s*\(' --type ts --type tsx

# 查找 ReplaceListType 定义
rg -nP -C2 'type\s+ReplaceListType' --type ts

Length of output: 336


🏁 Script executed:

#!/bin/bash
# 查找 RangePickerProps 与 PickerProps 类型定义
rg -nP 'interface\s+RangePickerProps\b' -n -g '*.ts' -g '*.tsx'
rg -nP 'interface\s+PickerProps\b' -n -g '*.ts' -g '*.tsx'
# 查找所有 onChange? 签名,确认第二参数是否允许 null
rg -nP 'onChange\?\s*:' -n -g '*.ts' -g '*.tsx'

Length of output: 779


🏁 Script executed:

#!/bin/bash
# 查看 RangePickerProps 接口及 onChange 签名
rg -nP -C5 'interface\s+RangePickerProps' -n src/PickerInput/RangePicker.tsx
rg -nP -C5 'onChange\?:' -n src/PickerInput/RangePicker.tsx

# 查看 PickerProps 接口及 onChange 签名
rg -nP -C5 'interface\s+PickerProps' -n src/PickerInput/SinglePicker.tsx
rg -nP -C5 'onChange\?:' -n src/PickerInput/SinglePicker.tsx

Length of output: 2090


修复类型定义并仅在 clear 时将 dateStrings 设为 null

  • src/PickerInput/hooks/useRangeValue.ts: 将 everyEmpty 判断改为 val == null,并将 onChange 第二参改为 isNullValue && everyEmpty ? null : getDateTexts(clone)
  • src/PickerInput/RangePicker.tsx (69–72):在 RangePickerProps 中将 onChange 签名的 dateStrings: [string, string] 修改为 dateStrings: [string, string] | null
  • src/PickerInput/SinglePicker.tsx (53,108):在 PickerPropsReplacedPickerProps 中将 dateString: string | string[] 修改为 string | string[] | null
🤖 Prompt for AI Agents
In src/PickerInput/hooks/useRangeValue.ts around lines 286–291, change the
empty-check to treat null/undefined as empty by using val == null instead of
!val, and change the onChange second argument to only be null when the overall
value is null AND every item is null: isNullValue && everyEmpty ? null :
getDateTexts(clone). Also update types: in src/PickerInput/RangePicker.tsx
(lines ~69–72) change RangePickerProps onChange signature so dateStrings is
typed as [string, string] | null, and in src/PickerInput/SinglePicker.tsx (lines
~53 and ~108) change PickerProps and ReplacedPickerProps dateString types from
string | string[] to string | string[] | null so callers can receive null on
clear.

}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/picker.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ describe('Picker.Basic', () => {
onChange.mockReset();

clearValue();
expect(onChange).toHaveBeenCalledWith(null, '');
expect(onChange).toHaveBeenCalledWith(null, null);
expect(isOpen()).toBeFalsy();

openPicker(container);
Expand Down
2 changes: 1 addition & 1 deletion tests/range.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ describe('Picker.Range', () => {
expect(onChange).toHaveBeenCalledWith([expect.anything(), null], ['1990-09-11', '']);

clearValue();
expect(onChange).toHaveBeenCalledWith(null, ['', '']);
expect(onChange).toHaveBeenCalledWith(null, null);
onChange.mockReset();

// Not allow empty with startDate
Expand Down