gpt4 book ai didi

typescript 函数重载奇怪的行为

转载 作者:行者123 更新时间:2023-12-03 23:39:30 25 4
gpt4 key购买 nike

我正在尝试了解函数重载在 Typescript 中的工作原理,但我不明白。检查此代码段( ts playground )(仅使用一个声明以使其尽可能简单):

function foo(x: number): 42

function foo(x: number) {
return x
}

const y = foo(23)
有两点不对:
  • 函数声明中没有 TS 错误,即使实际返回类型显然与重载签名不匹配
  • y 的推断值是 42

  • screenshot from ts playground
    相反,如果我只是在函数实现上声明返回类型,那么事情会按预期工作(或失败!):
    function foo(x: number): 42 {
    return x // -> Type 'number' is not assignable to type '42'.(2322)
    }

    const y = foo(4)

    最佳答案

    让我们解决第一个问题:

    no TS error on function declaration, even when the actual return type clearly doesn't match the overload signature


    如果你看看这个 doc (从那时起已弃用,但我想它仍然有效),他们说:

    In order for the compiler to pick the correct type check, it follows a similar process to the underlying JavaScript. It looks at the overload list and, proceeding with the first overload, attempts to call the function with the provided parameters. If it finds a match, it picks this overload as the correct overload. For this reason, it’s customary to order overloads from most specific to least specific.


    我的猜测是,当您编写实现时,对于您声明的每个重载,它都会尝试使用它来调用您的函数。我不知道这是否有意义。让我们看一个例子:
    function foo(x: number): 42 // ok since 42 is compatible with number (number is wider than 42)

    function foo(x: number) {
    return x
    }

    const y = foo(23)
    如果您获取签名,并尝试用它调用您的函数,则它是“兼容的”。 x 是一个数字,42 也是一个数字,我们实现的返回类型表示 x 是一个数字。
    如果我这样做:
    function foo(x: number): 42 // error: not compatible since 42 is not compatible with 32

    function foo(x: number) {
    return 32
    }
    我收到一个错误。另一条道路:
    function foo(x: number): 'text1'
    function foo(x: string): 'text2'

    function foo(x: number | string) {
    return x // why is there no error?
    }

    //y is "text1" (no, it's a number!!!)
    const y = foo(42)


    //there is no error because if you take the signature, you can call your function with it -> x is a number so compatible with number | string and 'text1' is compatible with number | string
    那么你可能会问为什么会这样?如果你从下面的角度来看,它会更容易推理。
    不是

    Can I call my signature with my function implementation?


    相反

    If I take one of my signatures, can I call my function implementation with it?


    不要将重载视为函数实现必须满足的某种要求。你有没有注意到错误是在重载上而不是在函数实现上?重载必须与函数实现兼容。

    第二点:

    the inferred value of y is 42


    如果将鼠标悬停在函数实现上,您会看到它只显示重载。
    最新版 doc说:

    The signature of the implementation is not visible from the outside.When writing an overloaded function, you should always have two ormore signatures above the implementation of the function.


    它们提供了人们常犯的一个常见错误:
    function fn(x: string): void;
    function fn() {
    // ...
    }
    // Expected to be able to call with zero arguments
    fn();
    Expected 1 arguments, but got 0.
    实现本身不算作重载。
    所以在调用函数时只能看到重载:
    const y = foo(23)

    所以考虑到这一点,明智地使用它们重载。剩下的就是你的责任。顺便说一句,在您的用例中,您根本不需要使用重载。只有当你至少有两个时才应该使用它。

    关于 typescript 函数重载奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66569814/

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