gpt4 book ai didi

TypeScript - 泛型被错误地推断为未知

转载 作者:行者123 更新时间:2023-12-01 11:12:09 25 4
gpt4 key购买 nike

我有以下通用功能:

export function useClientRequest<T, R extends (...args: any) => AxiosPromise<T>>(
func: R,
...args: Parameters<R>
): [T | undefined, boolean, AxiosError | undefined] {
// Irrelevant
}

总而言之,函数的返回值包含一个类型为 T 的值,应该按照上面的描述进行推断。

然后我尝试按如下方式使用它:
interface Foo {
// ...
}

function fooGetter(url: string): AxiosPromise<Foo> {
return Axios.get<Foo>(url);
}

const [data] = useClientRequest(fooGetter, 'url.com');

但是我的 IDE 报告 data类型为 unknown , 因为 T被推断为 unknown .

我做错了什么还是这是 TypeScript 的限制?

typescript v3.7.2

我知道我可以指定类型参数。我想知道为什么它们被错误地推断出来,以及我是否可以以某种方式更改实现以帮助推断机制。

最佳答案

来自 TypeScript specifications :

Type parameters may be referenced in parameter types and return type annotations, but not in type parameter constraints, of the call signature in which they are introduced.



鉴于您的函数签名,
<T, R extends (...args: any) => AxiosPromise<T>>(
func: R, ...args: Parameters<R>
): [T | undefined, boolean, AxiosError | undefined]

,我对上述声明的解释是, T出现在类型参数约束签名 extends (...args: any) => AxiosPromise<T>参数 R因此无法正确解决。 unknown就是 implicit default constraint type泛型类型参数。

所以这些人为的例子会起作用:
declare function fn0<T, U extends T>(fn: (t: T) => U): U
const fn0Res = fn0((arg: { a: string }) => ({ a: "foo", b: 42 })) // {a: string; b: number;}

declare function fn1<T, F extends (args: string) => number>(fn: F, t: T): T
const fn1Res = fn1((a: string) => 33, 42) // 42

在接下来的两个示例中,编译器推断 T成为 unknown , 因为 T仅在 U 的调用签名约束中引用并且不用于函数参数代码位置以获得进一步的编译器提示:
declare function fn2<T, U extends (args: T) => number>(fn: U): T
const fn2Res = fn2((arg: number) => 32) // T defaults to unknown

declare function fn3<T, U extends (...args: any) => T>(fn: U): T
const fn3Res = fn3((arg: number) => 42) // T defaults to unknown

可能的解决方案(选择最合适的)

1.) 可以引入类型参数 TR仅用于函数参数和返回类型:
declare function useClientRequest2<T, R extends any[]>(
func: (...args: R) => Promise<T>,
...args: R
): [T | undefined, boolean, AxiosError | undefined]

const [data] = useClientRequest2(fooGetter, 'url.com'); // data: Foo | undefined

2.) 这是条件类型的替代方案(更详细一点):
declare function useClientRequestAlt<R extends (...args: any) => Promise<any>>(
func: R,
...args: Parameters<R>
): [ResolvedPromise<ReturnType<R>> | undefined, boolean, AxiosError | undefined]

type ResolvedPromise<T extends Promise<any>> = T extends Promise<infer R> ? R : never
const [data2] = useClientRequestAlt(fooGetter, 'url.com'); // const data2: Foo | undefined

Playground

关于TypeScript - 泛型被错误地推断为未知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58779360/

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