gpt4 book ai didi

typescript 。过滤功能属性和 `Cannot invoke an expression whose type lacks a call signature.`

转载 作者:搜寻专家 更新时间:2023-10-30 21:48:37 24 4
gpt4 key购买 nike

我正在实现一个 call 函数,该函数接收对象和属性名称,然后在传递的属性处调用驻留在传递的对象中的函数。

function call<
T,
K extends {
[K in keyof T]: T[K] extends Function ? K : never
}[keyof T],
>(t: T, func: K) {

t[func]();
}

看起来 ts 对此很满意并正确地过滤了属性(没有 prop,只有 do 可用):

enter image description here

但它还在我调用函数的行上显示错误:t[func]();:

Cannot invoke an expression whose type lacks a call signature.
Type '{}' has no compatible call signatures.

我找到了类似的 issue [Type deduction using mapped types and generics]然而它作为另一个 issue [Call signatures of union types] 的副本被关闭.显然问题是第二个泛型参数实际上是所有满足条件的属性名称的联合类型。

除了转换为 any 之外,还有其他方法可以解决这个问题吗?

附言:Playground

最佳答案

Typescript 无法计算出您对属性的过滤意味着 T[K] 始终是一个函数。您可以稍微反转您的约束,以指定 T 扩展具有 ()=>void

类型属性的内容
function call<
T extends { [P in K]: ()=> void },
K extends keyof T
>(t: T, func: K) {

t[func]();
}

class Test {
prop: string = "";
doStuff(): void {}
}

call(new Test(), "prop") // error
call(new Test(), "doStuff") // ok

不过请注意,您可能会考虑在原始函数中使用断言,上面的版本在避免断言和类型安全的同时并不能帮助智能感知确定可以为第二个参数分配哪些可能的值,所以不要这样:

enter image description here

你得到这个:enter image description here

虽然在这种情况下通常应该避免断言,但我们确信类型实际上是正确的,因为我们对键有约束,所以这个版本也应该没问题:

function call2<
T,
K extends {
[K in keyof T]: T[K] extends ()=> void ? K : never
}[keyof T],
>(t: T, func: K) {

(t[func] as any as ()=> void)();
}

关于 typescript 。过滤功能属性和 `Cannot invoke an expression whose type lacks a call signature.`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50075560/

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