typescript - 在打字稿中定义 lambda 函数的问题
问题描述
我只是坚持使用打字稿中的以下 lambda 函数定义。这可能是一个新手问题。
type P = { id: string }
type F = <T>(x: T) => string
const f: F = (x: P) => x.id
f({ id: 'abc' }
但它一直在抱怨以下内容:
类型 '(x: P) => string' 不可分配给类型 'F'。
参数“x”和“x”的类型不兼容。
类型“T”不能分配给类型“P”。
更新#1
我只是评论了为什么我需要一个通用函数的上下文。我正在执行一个函数来验证输入对象,并且该对象的每个路径都可以配置以进行验证,如下所示:
type Option = { path: string; isVerified: <T>(t: T) => boolean }
const verify = (obj: any, options: Option[]): boolean => {
const results = options.map(option => {
const { path, isVerified } = option
return isVerified(obj[path])
})
return results.every(x => x)
}
type A = number
type B = string
const obj = { a: 1 as A, b: 'abc' as B }
verify(obj, [
{ path: 'a', isVerified: (x: A): boolean => x > 0 },
{ path: 'b', isVerified: (x: B): boolean => x.startsWith('a') }
])
更新#2
感谢第一个答案,它解决了中列出的问题Update #1
。然而,Update #1
实际上是一个简化的问题。在实际情况下,path
underOption
类型可能是string
or RegExg
,这使得响应的代码Paths[K]
无效,如下所示:
type Option = { path: string | RegExp; isVerified: <T>(t: T) => boolean }
const verify = (obj: any, options: Option[]): boolean => {
const results = Object.keys(obj).map(k => {
const verifiers = options
.filter(opt =>
typeof opt.path === 'string' ? opt.path === k : opt.path.test(k)
)
.map(x => x.isVerified)
return verifiers.every(verify => verify(obj[k]))
})
return results.every(x => x)
}
type A = number
type B = string
const obj = { a: 1 as A, b: 'abc' as B }
verify(obj, [
{ path: 'a', isVerified: (x: A): boolean => x > 0 },
{ path: /b/, isVerified: (x: B): boolean => x.startsWith('a') }
])
有关更多详细信息,请参阅Playground 链接。
它一直在下面抱怨:
类型 '(x: number) => boolean' 不可分配给类型 '(t: T) => boolean'。
参数“x”和“t”的类型不兼容。
类型“T”不能分配给类型“数字”。
解决方案
关于示例代码:
type P = { id: string }
type F = <T>(x: T) => string
const f: F = (x: P) => x.id
该类型F
是从任何类型T
到的泛型函数string
;所以本质上,对于一个函数来说,F
它必须接受任何类型的参数。您的函数f
只接受 type 的参数P
,因此该函数不是 type F
。
关于您要解决的实际问题,这里真正的问题是Option
应该是联合类型,因为参数类型isVerified
取决于 的值path
:
type Option = {
path: 'a',
isVerified: (t: number) => boolean
} | {
path: 'b',
isVerified: (t: string) => boolean
}
为了使这个联合类型更容易为实际用例(可能有更多字段)声明,Paths
为您正在验证的对象定义一个类型,然后构造Option
为映射类型:
type Paths = { a: number, b: string }
type Option = {
[K in keyof Paths]: {
path: K,
isVerified: (t: Paths[K]) => boolean
}
}[keyof Paths]
现在您的函数调用verify
将进行类型检查,甚至会为您推断参数类型,而无需您编写显式注释:
const obj = { a: 1, b: 'abc' }
// OK
verify(obj, [
{ path: 'a', isVerified: x => x > 0 },
{ path: 'b', isVerified: x => x.startsWith('a') }
])
此外,如果参数类型错误,您将收到类型错误(根据需要)isVerified
,因为path
属性缩小了isVerified
应具有的类型:
// type error
verify(obj, [
{ path: 'a', isVerified: x => x.startsWith('a') },
{ path: 'b', isVerified: x => x > 0 }
])
您还需要进行另一项编辑 -verify
函数中的类型断言,因为否则isVerified
会被推断为采用类型参数never
(即交集 number & string
):
const verify = (obj: any, options: Option[]): boolean => {
const results = options.map(option => {
const { path, isVerified } = option
// this line needs a type assertion
return (isVerified as (t: Paths[typeof path]) => boolean)(obj[path])
})
return results.every(x => x)
}
推荐阅读
- android - 如何在Android上的gridview中为特定行设置不同的选择器(颜色)
- r - 如何将分位数结果拆分为 5 个不同的数据帧?
- javascript - 为什么我所要求的价值没有改变?
- math - 如何将 UUID 空间划分为 N 个大小相等的分区?
- javascript - 无法获得选中单选按钮的值
- sql - HiveQL 中的计数总和
- java - 使用 & 的奇怪的 Java 强制转换语法
- python - Sklearn 通过句子对文档进行矢量化以进行分类
- toad - 如何将 TOAD 布局恢复为其原始布局?
- javascript - 用于计算返回文档中唯一 ID 的 Mongo 聚合速度很慢