如何通过排除特定类实例缩小对象类型?求更简洁实现方案
问题
我希望在接收对象参数的函数中禁止传入Date实例,目前的实现方式如下:
type ExcludeDate<T> = T extends Date ? never : T function f<T extends object>(arg: T & ExcludeDate<T>) { } f(new Date()) // Error: Argument of type 'Date' is not assignable to parameter of type 'never'.(2345)
请问有没有更简洁的实现方式?我试过下面这种写法,但没法生效:
function f<T extends Exclude<object, Date>>(arg: T) { }
解决方案
你的写法为什么不生效?
Exclude<object, Date> 其实还是等于 object,因为Exclude只能用来排除联合类型里的成员,而object是单一类型,Date只是它的子类型,所以这个约束根本过滤不掉Date实例。
更简洁的实现
直接把条件判断整合到参数类型里,不用额外定义ExcludeDate类型:
function f<T extends object>(arg: T extends Date ? never : T) { } f(new Date()) // 报错:类型 'Date' 不能赋值给类型 'never' f({ name: "test" }) // 正常通过 f([1, 2, 3]) // 正常通过(数组属于object的子类型)
如果需要严格限制为普通对象(排除数组、Date等内置对象),可以把object换成Record<string, unknown>:
function f<T extends Record<string, unknown>>(arg: T extends Date ? never : T) { } f([1,2,3]) // 此时数组会报错,不符合约束
内容的提问来源于stack exchange,提问作者Franck Wolff
相关产品推荐
相关产品推荐

