为什么在重载字符串参数时必须在实现之前有一般类型声明?

时间:2017-08-02 20:36:35

标签: typescript overloading signature

TypeScript支持重载字符串参数,以便在使用某些参数调用时可以正确键入返回any的方法。

这在两个地方的规范中定义: https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#1.8 https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#3.9.2.4

然而,要使这些正常工作可能会很困难。这是一个具有通用get的示例类。我希望在将字符串"a""b"传递给此函数时提供特定类型,而在所有其他情况下,返回类型为any

我包含两个专门的签名,然后提供一般签名,然后提供具有一般签名的实现。以下代码正确地报告了xy的前两个分配的错误,但如果我删除了常规签名(get(name: string): any),则会收到错误:Argument of type '"c"' is not assignable to parameter of type '"b"'.为什么除了实施签名之外,还是一般签名要求吗?

export default class Example {
  contents: any
  get(name: "a"): number
  get(name: "b"): string
  // Why is this required???
  get(name: string): any
  get(name: string): any { return this.contents[name] }
}


let w = new Example()

// Expected errors
// Type 'number' is not assignable to type 'string'.
let x: string = w.get("a")
// Type 'string' is not assignable to type 'number'.
let y: number = w.get("b")

// I get an error here only if I remove the general signature before the
// implementation of get.
// Argument of type '"c"' is not assignable to parameter of type '"b"'.
let z: string[] = w.get("c")

1 个答案:

答案 0 :(得分:2)

请注意section 6.2 of the spec, "Function overloads"

的最后一行
  

请注意,实际函数实现的签名不包含在类型中。

这是有道理的,因为实现的签名需要匹配所有可能的签名,如果它包含在最终签名中,这可能会导致比我们实际想要的更一般的签名。例如:

function foo(type: "number", arg: number)
function foo(type: "string", arg: string)
function foo(type: "number" | "string", arg: number | string) {
    // impl here
}

由于之前的签名,实施的签名是必要的,但如果它包含在最终签名中,则允许以下内容,尽管这正是我们想要阻止的:

foo("number", "string param")