Material UI自定义useBreakPoint钩子出现TypeScript类型报错如何解决?
问题根因分析
- 第一个报错
Expected 2 arguments, but got 1.的核心原因:你定义的Limit联合类型包含了between,而从Breakpoints接口定义可以看到,between方法需要传入两个断点参数,你当前的实现无论limit取什么值都只传1个参数,TS的类型检查能识别到不同limit对应的方法参数数量不一致,因此抛出参数不匹配错误。 - 第二个
string类型无法索引Breakpoints报错的原因:通用string类型没有被限定为Breakpoints的合法属性名,TS无法确认你传入的字符串一定是Breakpoints上存在的方法,因此默认按any处理,触发类型警告。 - 第三个
keyof Limit报错的原因:keyof是用来提取对象类型的键名的,你把它用在字符串联合类型Limit上,实际得到的是字符串原型的所有属性名(比如toString、length等),和Breakpoints的属性完全无关,自然无法用来索引Breakpoints。
解决方案
分两种常见业务场景提供实现:
场景1:不需要支持between区间查询
如果你的业务里不需要用到区间查询,直接把Limit类型里的between去掉即可,剩下的up、down、only都是单参数方法,类型完全匹配:
import { useTheme } from '@material-ui/core'; import useMediaQuery from '@material-ui/core/useMediaQuery'; import { Breakpoint, Breakpoints } from '@material-ui/core/styles/createBreakpoints'; // 只保留单参数的三个方法,和Breakpoints定义强关联 type Limit = keyof Pick<Breakpoints, 'up' | 'down' | 'only'>; function useBreakPoint(limit: Limit, breakpoint: Breakpoint): boolean { const theme = useTheme(); return useMediaQuery(theme.breakpoints[limit](breakpoint)); } export default useBreakPoint
场景2:需要支持between区间查询
如果要支持区间查询,需要用TS函数重载来适配不同limit对应的参数规则:
import { useTheme } from '@material-ui/core'; import useMediaQuery from '@material-ui/core/useMediaQuery'; import { Breakpoint, Breakpoints } from '@material-ui/core/styles/createBreakpoints'; type Limit = keyof Pick<Breakpoints, 'up' | 'down' | 'between' | 'only'>; // 函数重载:单参数方法的签名 function useBreakPoint(limit: Exclude<Limit, 'between'>, breakpoint: Breakpoint | number): boolean; // 函数重载:between方法的签名 function useBreakPoint(limit: 'between', start: Breakpoint | number, end: Breakpoint | number): boolean; // 内部实现 function useBreakPoint(limit: Limit, ...args: (Breakpoint | number)[]): boolean { const theme = useTheme(); // 参数规则已通过重载限制,不会出现不匹配问题,可忽略此处类型警告 // @ts-ignore return useMediaQuery(theme.breakpoints[limit](...args)); } export default useBreakPoint
实现后支持两种调用方式:
- 单参数调用:
useBreakPoint('down', 'md') - 区间调用:
useBreakPoint('between', 'sm', 'lg')
内容的提问来源于stack exchange,提问作者Hans
相关产品推荐
相关产品推荐

