typescript - 未捕获打字稿函数返回类型
问题描述
我在这里缺少什么,
我认为它应该是result
类型{foo: unknown, bar: unknown, baz: unknown}
{foo: number, bar: boolean, baz: string}
export function apply<A, B extends {[P in keyof A]: B[P]}>(
functions: {[P in keyof A]: (a: A[P]) => B[P]},
data: {[P in keyof A]: A[P]},
): {[P in keyof A]: B[P]} {
const result = {} as {[P in keyof A]: B[P]}
const keys = Object.keys(functions) as (keyof A)[]
for(const key of keys)
result[key] = functions[key](data[key])
return result
}
const functions = {
foo: (a: string) => a.length,
bar: (a: number) => a === 42,
baz: (a: boolean) => a ? 'true' : 'false'
}
const data = {foo: 'foo', bar: 42, baz: true}
const result = apply(functions, data)
解决方案
首先让我们检查一下当前尝试的问题,即您为两个参数提供的类型。
functions: {[P in keyof A]: (a: A[P]) => B[P]},
data: {[P in keyof A]: A[P]}
看起来您希望该类型A[P]
表示A
对象的值类型。这里的问题是对 type 没有限制A
,所以我们没有什么可以用来推断值的更具体的类型。因此,它们被推断为具有最一般的类型:unknown
.
考虑到您可以在调用apply
函数时手动指定泛型参数。就像是:
type A = {} // ??? what to put here?
type B = {} // ??? what to put here?
const result = apply<A, B>(functions, data)
问题是我不确定A
在这个例子中我会给出什么类型。A
事实上,除了你所看到的之外,我不确定这个构造中是否存在有效的类型{foo: unknown, bar: unknown, baz: unknown}
:
因此,与其对上述参数使用映射类型,为什么不将这些限制添加到泛型签名本身呢?看起来您希望functions
参数是一个包含单个参数函数的对象。让我们限制泛型A
以立即满足该条件:
A extends Record<string, (a: any) => any>
而对于B
,这是您的数据类型,它应该与 中每个相应函数的参数类型匹配A
。我们也可以在通用签名中应用该限制:
B extends {[P in keyof A]: Parameters<A[P]>[0]}
最后,对于返回类型,这是另一个对象,但不是对应于 的参数类型A
,而是返回类型:
{[P in keyof A]: ReturnType<A[P]>
把所有这些放在一起:
function apply<A extends Record<string, (a: any) => any>, B extends {[P in keyof A]: Parameters<A[P]>[0]}>(
functions: A,
data: B
): {[P in keyof A]: ReturnType<A[P]> {
const result = {} as {[P in keyof A]: B[P]}
const keys = Object.keys(functions) as (keyof A)[]
for(const key of keys)
result[key] = functions[key](data[key])
return result
}
const functions = {
foo: (a: string) => a.length,
bar: (a: number) => a === 42,
baz: (a: boolean) => a ? 'true' : 'false'
}
const data = {foo: 'foo', bar: 42, baz: true}
const result = apply(functions, data)
// The type of `result` is inferred to be:
// {
// foo: number;
// bar: boolean;
// baz: "true" | "false";
// }
推荐阅读
- flutter - Flutter:未处理的异常:刷新页面时发生在dispose()之后调用的setState()
- excel - 从具有多个页面的网站中抓取数据
- authorization - 在 HCL OneTest Data 中,admin 用户是否有权更改用户的权限?
- apk - 在新的 Google Play 控制台 UI 中找不到“编辑发布”选项
- java - 在运行时更改超时 - Elasticsearch RestHighLevelClient
- apache - 漂亮的 RewriteRule 回到旧格式
- php - 为什么 CI 库不发送电子邮件也不显示错误
- android - android是否支持通知图标的矢量可绘制?
- azure-data-factory - 有没有办法对 Azure 数据流中不同数量的列进行自定义动态映射或任何其他选项来实现这一点?
- c# - 从 ASP.NET MVC 视图向控制器传递值