gpt4 book ai didi

typescript - 在 typescript 中定义 lambda 函数的问题

转载 作者:行者123 更新时间:2023-12-04 10:58:29 25 4
gpt4 key购买 nike

我只是在 typescript 中坚持使用以下 lambda 函数定义。这可能是一个新手问题。

type P = { id: string }
type F = <T>(x: T) => string
const f: F = (x: P) => x.id
f({ id: 'abc' }

但它一直在提示以下内容:

Type '(x: P) => string' is not assignable to type 'F'.

Types of parameters 'x' and 'x' are incompatible.

Type 'T' is not assignable to type '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其实是一个简化的问题。在真实情况下, pathOption类型可以是 stringRegExg ,这使得代码回答 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') }
])

Play ground link更多细节。

它一直在下面提示:

Type '(x: number) => boolean' is not assignable to type '(t: T) => boolean'.

Types of parameters 'x' and 't' are incompatible.

Type 'T' is not assignable to type 'number'.




最佳答案

关于示例代码:

type P = { id: string }
type F = <T>(x: T) => string
const f: F = (x: P) => x.id

型号 F是任何类型的泛型函数 Tstring ;所以本质上,对于类型为 F 的函数它必须接受任何类型的参数。您的职能 f只接受 P 类型的参数,所以函数不是 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)
}

Playground Link

关于typescript - 在 typescript 中定义 lambda 函数的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59013871/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com