2017-08-02 4 views
0

TypeScript prend en charge les paramètres de chaîne de surcharge afin que les méthodes renvoyant any puissent être correctement typées lorsqu'elles sont appelées avec certains arguments.Pourquoi doit-il y avoir une déclaration de type générale avant l'implémentation lors de la surcharge des paramètres de chaîne?

Ceci est défini dans la spécification en deux endroits: 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

Cependant, ceux-ci se fonctionnent correctement peut être difficile. Voici une classe d'exemple qui a un get générique. Je souhaite fournir des types spécifiques lorsque vous transmettez les chaînes "a" ou "b" à cette fonction et, dans tous les autres cas, que le type de retour soit any.

J'inclus les deux signatures spécialisées, puis fournissez une signature générale, puis fournissez l'implémentation, qui a la signature générale. Le code suivant signale correctement l'erreur pour les deux premières affectations à x et y, mais si je supprime la signature générale (get(name: string): any), j'obtiens l'erreur: Argument of type '"c"' is not assignable to parameter of type '"b"'. Pourquoi la signature générale nécessite-t-elle en plus de la signature sur l'implémentation?

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") 

Répondre

2

Notez la dernière ligne de section 6.2 of the spec, "Function overloads"

Note that the signature of the actual function implementation is not included in the type.

Cela est logique, car la signature de la mise en œuvre doit correspondre à toutes les signatures possibles, et si elle était incluse dans la signature finale, cela pourrait conduire à une signature plus générale que nous voulons réellement. Par exemple:

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

La signature de la mise en œuvre est nécessaire en raison des signatures précédentes, mais si elle était incluse dans la signature finale, ce qui suit serait permis bien que ce soit exactement ce que nous voulons éviter:

foo("number", "string param")