gpt4 book ai didi

typescript 没有正确进行案例分析

转载 作者:行者123 更新时间:2023-12-05 05:33:49 25 4
gpt4 key购买 nike

假设我们要定义一个函数,该函数接受另一个函数及其参数,并输出使用参数调用的函数。这是一个很好的例子,我们希望 typescript 进行正确的案例分析。见下文。

let fns = {
A: (x: string) => 'a' + x,
B: (y: number) => 100 + y
}

type fn = typeof fns[keyof typeof fns]

const combine = <T extends fn>(fn: T, param: Parameters<T>[0]) => {
return fn(param)
}

问题是 typescript 在 param 一词上(在与 return 一词的行上)给我以下错误:'string | 类型的参数number' 不可分配给 'never' 类型的参数。类型“string”不可分配给类型“never”。ts(2345)

出于某种原因,它将两种类型的输入组合成一种类型,而不是理解 T 只会是一种或另一种。帮助!

最佳答案

(用A和B分别指代签名)

TypeScript 实际上在这里是正确的,因为 T extends fn 意味着 T 只能是“A”或“B”。 T extends fn 是一个约束,意味着 T 必须可分配给 fn。当然,“A”和“B”可分配给 fn,但类型 A | B 可分配给 fn

这意味着有人可以这样调用您的函数:

combine<fn>(fns.A, 0);

如果 TypeScript 允许这样做,那么这个调用就是有效的!这将导致意外和不良行为。但别担心,我有两种可能的解决方法,每种方法各有利弊。


一种是使用外部签名,内部签名是这样写的:

function combine<T extends fn>(fn: T, param: Parameters<T>[0]): ReturnType<T>;
function combine<T extends (x: unknown) => R, R>(fn: T, param: Parameters<T>[0]): R {
return fn(param);
}

它有点丑陋且不安全,但它在保留原始签名的同时确实有效。但是,正如我上面提到的,人们可以使用 fn 类型而不是“A”或“B”来调用它。

Playground


与第一个类似,这个使用单独的重载。它比第一个稍微好一些,因为它可以防止用户使用函数的联合来调用它,但要键入的内容要多得多。

function combine(fn: typeof fns.A, param: string): string;
function combine(fn: typeof fns.B, param: number): number;
function combine<T extends (x: unknown) => R, R>(fn: T, param: Parameters<T>[0]): R {
return fn(param)
}

Playground

可能有更好的解决方案,但我早上还没喝咖啡。希望您至少理解为什么这是一个错误,但当我想到它们时,我仍然会使用更好的解决方案来编辑​​答案。

关于 typescript 没有正确进行案例分析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73760581/

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