使用MomentAdapter时,MUI DatePicker的onChange事件类型签名是什么?
MUI DatePicker搭配MomentAdapter时onChange的正确类型签名问题
问题说明
使用MUI的DatePicker搭配MomentAdapter时,控制台打印显示date是Moment对象,但TypeScript报错提示期望Date类型;在StackBlitz复现该场景时,date又变成了Date类型。需要明确onChange事件的正确类型签名。
用户原代码:
import * as React, { useState } from 'react'; import TextField from '@mui/material/TextField'; import { AdapterMoment } from '@mui/x-date-pickers/AdapterMoment'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { DatePicker } from '@mui/x-date-pickers/DatePicker'; import { Moment } from 'moment'; function App() { const [value, setValue] = useState<Moment | null>(); return ( <LocalizationProvider dateAdapter={AdapterMoment}> <DatePicker value={value} onChange={(date: Moment | null) => { setValue(date); console.log(date); }} renderInput={(params) => <TextField {...params} />} /> </LocalizationProvider> ) }
原因解析
这个问题的核心是MUI X DatePicker的类型会随使用的适配器自动推断,但以下情况会导致类型不匹配:
- 本地项目中实际运行时用了MomentAdapter,所以回调参数是Moment对象,但TypeScript没正确识别适配器对应的类型,因此报错期望Date。
- StackBlitz中可能依赖版本不同,或者默认使用了原生Date适配器,所以参数类型变成了Date。
正确的类型处理方式
方式1:让TypeScript自动推断类型
直接移除onChange参数的手动类型声明,TypeScript会根据LocalizationProvider传入的AdapterMoment自动推断出参数类型为Moment | null,既省心又不会出错:
import * as React, { useState } from 'react'; import TextField from '@mui/material/TextField'; import { AdapterMoment } from '@mui/x-date-pickers/AdapterMoment'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { DatePicker } from '@mui/x-date-pickers/DatePicker'; import { Moment } from 'moment'; function App() { const [value, setValue] = useState<Moment | null>(); return ( <LocalizationProvider dateAdapter={AdapterMoment}> <DatePicker value={value} onChange={(date) => { setValue(date); console.log(date); }} renderInput={(params) => <TextField {...params} />} /> </LocalizationProvider> ) }
方式2:显式指定DatePicker的泛型类型
如果需要手动指定类型,可以给DatePicker添加泛型参数Moment,明确它处理的日期类型,这样TS就能正确识别onChange的参数类型:
import * as React, { useState } from 'react'; import TextField from '@mui/material/TextField'; import { AdapterMoment } from '@mui/x-date-pickers/AdapterMoment'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { DatePicker } from '@mui/x-date-pickers/DatePicker'; import { Moment } from 'moment'; function App() { const [value, setValue] = useState<Moment | null>(); return ( <LocalizationProvider dateAdapter={AdapterMoment}> <DatePicker<Moment> value={value} onChange={(date: Moment | null) => { setValue(date); console.log(date); }} renderInput={(params) => <TextField {...params} />} /> </LocalizationProvider> ) }
额外注意点
- 确保项目中
@mui/x-date-pickers、@mui/material和moment的版本兼容,版本不匹配很容易导致类型推断异常。 - 不要同时安装多个日期适配器(比如
AdapterDateFns和AdapterMoment),避免类型冲突。
内容的提问来源于stack exchange,提问作者Sasgorilla
相关产品推荐
相关产品推荐

