DayPicker 的 DayProps 类型别名解析:自定义日期单元格组件的类型契约
DayPicker 的 DayProps 类型别名解析:自定义日期单元格组件的类型契约
DayProps 是 react-day-picker 中用于描述日期单元格组件 Day 所接收 props 的类型别名,是开发者通过 components.Day 自定义日历单元格(如包裹 tooltip、调整 <td> 结构、展示日程条目)时必须遵循的类型契约。读完本文,你将准确掌握 DayProps 的定义方式、day 与 modifiers 两个核心字段的数据结构与取值规律,并能基于它写出类型安全的自定义日期单元格组件。
什么是 DayProps:从 Day 组件派生而来的类型别名
DayProps 并非独立手工声明的一组接口,而是通过 TypeScript 的 Parameters 工具类型从 Day 组件函数自动推导出来的:
DayProps = Parameters<typeof Day>[0]
也就是说,它等价于 Day 函数组件接收的第一个参数 props 的完整类型。这样设计的好处是单一事实来源(single source of truth):只要 Day 组件的签名发生变化,DayProps 就会同步更新,文档与 API 永远保持一致。
在源码 packages/react-day-picker/src/components/Day.tsx 中,这一别名定义如下:
/** Props accepted by the {@link Day} component. */
export type DayProps = Parameters<typeof Day>[0];
而 Day 组件本身的签名(Day.tsx#L16-L26)是:
export function Day(
props: {
/** The day to render. */
day: CalendarDay;
/** The modifiers to apply to the day. */
modifiers: Modifiers;
} & HTMLAttributes<HTMLDivElement>,
) {
const { day, modifiers, ...tdProps } = props;
return <td {...tdProps} />;
}
从源码可以看出 DayProps 的完整结构为:
type DayProps = {
day: CalendarDay;
modifiers: Modifiers;
} & HTMLAttributes<HTMLDivElement>;
它与 DayButtonProps 的区别值得注意:DayButton 组件的 props 类型是 { day; modifiers } & ButtonHTMLAttributes<HTMLButtonElement>(见 packages/react-day-picker/src/components/DayButton.tsx)。两者共享 day 与 modifiers 两个核心字段,差异仅在继承的 HTML 属性基类——Day 继承的是 <div> 的属性集合,DayButton 继承的是 <button> 的属性集合,因为前者最终渲染为 <td> 单元格,后者渲染为可交互的 <button>。
DayProps 的两个核心字段
day: CalendarDay —— 被渲染的日期及其上下文
day 的类型是 CalendarDay 类,它并不是一个裸的 Date,而是对日期及其在日历中呈现上下文的封装。查看 packages/react-day-picker/src/classes/CalendarDay.ts 的源码,其字段包括:
| 字段 | 类型 | 含义 |
|---|---|---|
date |
Date |
该天所代表的日期对象 |
displayMonth |
Date |
当前日历中正在展示的月份;当 showOutsideDays 开启、出现相邻月份的日子时,用于判断该天实际所属的月份 |
outside |
boolean |
该天是否不属于当前展示的月份(构造时通过 dateLib.isSameMonth(date, displayMonth) 计算得出) |
isoDate |
string |
yyyy-MM-dd 格式的稳定字符串,便于用作 React key 或 data-* 属性(V9.11.2 起提供) |
displayMonthId |
string |
yyyy-MM 格式的展示月份标识(V9.11.2 起提供) |
dateMonthId |
string |
yyyy-MM 格式的该天实际所属月份标识(V9.11.2 起提供) |
dateLib |
DateLib |
日期工具函数集(标记为 @private,一般无需直接使用) |
此外 CalendarDay 还提供 isEqualTo(day) 方法,用于同时比较日期与展示月份是否相等。在自定义 Day 组件中,读取 day.date 即可拿到具体日期,判断 day.outside 可区分邻近月份的补白日期,而 day.isoDate 则非常适合作为单元格的稳定 key。
modifiers: Modifiers —— 应用于该天的修饰符集合
modifiers 的类型是 Record<string, boolean>,源码定义于 packages/react-day-picker/src/types/shared.ts#L277:
export type Modifiers = Record<string, boolean>;
它描述"哪些修饰符命中了这一天"。官方文档给出的典型取值示例为:
const modifiers: Modifiers = {
today: true, // 该天是今天
selected: false, // 该天未被选中
weekend: true, // 自定义的周末修饰符
};
内置修饰符(如 today、selected、disabled、focused、outside 等)与通过 modifiers prop 定义的自定义修饰符都会出现在该对象中,值为 true 表示命中、false 表示未命中。你的自定义 Day 组件可以依据 modifiers.selected、modifiers.disabled 等字段决定如何渲染单元格的样式或内容。
在实战中使用 DayProps:自定义日期单元格
DayProps 的典型应用场景是通过 components prop 覆盖默认的 Day 组件。官方自定义组件指南(apps/website/docs/guides/custom-components.mdx)给出了如下挂载方式:
<DayPicker
components={{
Day: CustomDayCell,
MonthGrid: CustomMonthGrid,
// 仅覆盖需要的组件,components 接受部分映射(partial map)
}}
/>
由于 Day 只负责渲染 <td> 单元格(交互与焦点管理由内部的 DayButton 负责),当你需要改变表格单元格的结构——例如在外层包裹 tooltip、添加装饰元素、展示日程条目——时,就应该自定义 Day;而如果只是改变按钮内部内容或交互行为,官方建议优先自定义 DayButton;仅修改文本内容时则优先使用 formatters(格式化函数)。
编写自定义 Day 组件时,务必遵循官方给出的可访问性与行为保持原则:
- 完整转发收到的 props(包括
aria-*、tabIndex、ref及事件处理器),以保留键盘导航与屏幕阅读器支持; - 渲染内置元素时,复用
useDayPicker()提供的classNames与labels,确保修饰符类名与 ARIA 文本保持一致; - 优先基于默认组件组合扩展,而不是在
Day中重建如焦点管理之类的内建行为(焦点管理属于DayButton的职责,见 DayButton.tsx#L22-L25)。
一个最小化的自定义单元格示例如下:
import { DayPicker, type DayProps } from "@daypicker/react";
function CustomDayCell(props: DayProps) {
const { day, modifiers, ...tdProps } = props;
return (
<td {...tdProps} data-iso={day.isoDate} data-outside={day.outside}>
{modifiers.today ? "★" : null}
{day.date.getDate()}
</td>
);
}
export function MyDatePicker() {
return <DayPicker components={{ Day: CustomDayCell }} />;
}
注意代码中通过解构将 day 与 modifiers 从 tdProps 中分离出来,确保剩余的 HTML 属性原样传递到 <td> 上——这与默认 Day 实现的处理方式(Day.tsx#L24)完全一致。
相关类型与组件的对照
| 类型/组件 | 定义位置 | 说明 |
|---|---|---|
DayProps |
packages/react-day-picker/src/components/Day.tsx#L28 | Day 组件接收的 props 类型,包含 day、modifiers 及 HTMLAttributes<HTMLDivElement> |
DayButtonProps |
packages/react-day-picker/src/components/DayButton.tsx#L29 | DayButton 组件接收的 props 类型,基类为 ButtonHTMLAttributes<HTMLButtonElement> |
CalendarDay |
packages/react-day-picker/src/classes/CalendarDay.ts | day 字段的类型,封装日期与其展示上下文 |
Modifiers |
packages/react-day-picker/src/types/shared.ts#L277 | modifiers 字段的类型,即 Record<string, boolean> |
如果想进一步了解 Day 函数组件的完整签名,可查阅官方 API 文档 Day 函数说明;关于自定义组件的完整指南、useDayPicker hook 及 DayPickerContext 的用法,可阅读 Custom Components 指南。仓库中还提供了完整的可运行示例 examples/CustomDayButton.tsx,它演示了如何基于 DayButtonProps(与 DayProps 结构同源)通过自定义 Context 实现双击选择日期等交互场景,可作为编写自定义日期组件的参考起点。