【问题标题】:TS2769: No overload matches this callTS2769:没有重载匹配此调用
【发布时间】:2021-07-12 18:09:34
【问题描述】:

我有一个函数接受 A 中定义的类型作为参数,但我想让输入更严格,所以我创建了 B。

interface A {
    readonly x: any;
}

interface B extends Omit<A, 'x'> {
    readonly x: number;
}

问题是,这个函数不接受 B 中的类型,即使它比 A 更严格。相反,我收到错误 No overload matches this call,说是 Type(props: B) =&gt; number is not assignable to type (props: A) =&gt; number"。

这个函数也不接受props: { x : number },给我一个类似的错误信息。

【问题讨论】:

  • 你能分享一个完整的例子吗?代码 sn -p 本身不会出错。

标签: javascript typescript


【解决方案1】:

问题是函数参数是contravariant。与正常值类型的可分配性相比,它们的可分配性是在相反的方向检查的。这就是为什么您不能将接受有限值子集的函数分配给接受更广泛值集的函数:

interface A {
    readonly x: unknown;
}

interface B extends Omit<A, 'x'> {
    readonly x: number;
}

declare function narrowerFn(props: B): number

const widerFn: (props: A) => number = narrowerFn // errror

playground link

这很有意义。由于目标端函数可以接受例如源端函数不知道如何处理的字符串。

但它完全相反:

interface A {
    readonly x: string;
}

interface B extends Omit<A, 'x'> {
    readonly x: number | string;
}

declare function widerFn(props: B): number

const narrowerFn: (props: A) => number = widerFn

playground link

由于现在目标端函数只能接受源端函数可以完美处理的值的子集。

【讨论】:

    【解决方案2】:

    首先,您不需要Omit。只需按如下方式覆盖该属性:

    interface A {
        readonly x: any;
    }
    
    interface B extends A {
        readonly x: number;
    }
    

    另外,我创建了以下示例来突出问题:

    TS Playground

    type FA = (props: A) => number;
    
    type FB = (props: B) => number;
    
    const fb: FB = ({ x }) => x + 1;
    
    const fa: FA = fb;
    
    // Unsafe usage, cause fb expects numbers, not strings
    console.log(fa({ x: '1' })); // Output "11" instead of 2
    

    【讨论】:

    • 这是对逆变的一个很好的解释,但问题中使用的Omit 的要点是定义一个接口扩展一个类型,该类型不是包含x 的更广泛定义的类型,这样继承不被违反。错误来自未包含在问题中的函数。
    • 你应该在问题上发布。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-13
    • 1970-01-01
    • 2020-02-18
    • 2021-03-13
    • 1970-01-01
    • 2021-06-07
    • 1970-01-01
    相关资源
    最近更新 更多