web-dev-qa-db-fra.com

TypeScript plusieurs types de retour avec des paramètres identiques

Contexte

En essayant d'entrer dans l'esprit de TypeScript, j'écris des signatures entièrement typées dans mes composants et services, ce qui s'étend à mes fonctions de validation personnalisées pour les formulaires angular2.

Je sais que je peux surcharger une signature de fonction , mais cela nécessite que les paramètres soient différents pour chaque type de retour car tsc compile chaque signature dans une fonction distincte:

function pickCard(x: {suit: string; card: number; }[]): number;
function pickCard(x: number): {suit: string; card: number; };
function pickCard(x): any { /*common logic*/ };

Je sais aussi que je peux retourner un seul type (comme une promesse) qui peut lui-même être de plusieurs sous-types:

private active(): Promise<void|null> { ... }

Cependant, dans le contexte des validateurs de formulaires personnalisés angular2, une seule signature (un paramètre de type FormControl) peut renvoyer deux types distincts: un Object avec des erreurs de formulaire ou null pour indiquer que le contrôle ne contient aucune erreur.

Cela, évidemment, ne fonctionne pas:

private lowercaseValidator(c: FormControl): null;
private lowercaseValidator(c: FormControl): Object {
    return /[a-z]/g.test(c.value) ? null : { lowercase: this.validationMessages.lowercase };
}

Pas plus

private lowercaseValidator(c: FormControl): null|Object {...}
private lowercaseValidator(c: FormControl): <null|Object> {...}

(Fait intéressant, je reçois les erreurs suivantes, plutôt que quelque chose de plus informatif:

error TS1110: Type expected.
error TS1005: ':' expected.
error TS1005: ',' expected.
error TS1128: Declaration or statement expected.

)

TL; DR

Suis-je parti simplement en utilisant

private lowercaseValidator(c: FormControl): any { ... }

qui semblerait nier l'avantage d'avoir des signatures de type?

Plus généralement, dans l'attente de l'ES6

Bien que cette question soit inspirée des validateurs de formulaires angular2, qui sont gérés directement par le framework, vous pouvez donc ne pas vous soucier de déclarer le type de retour, mais il est toujours généralement applicable, en particulier compte tenu des constructions ES6 comme function (a, b, ...others) {}

Il est peut-être simplement préférable de ne pas écrire de fonctions pouvant renvoyer plusieurs types, mais c'est plutôt idiomatique, en raison de la nature dynamique de JavaScript.

Références

12
msanford

Ok, c'est la bonne façon si vous voulez avoir des types appropriés:

type CustomType = { lowercase: TypeOfTheProperty };
// Sorry I cannot deduce type of this.validationMessages.lowercase,
// I would have to see the whole class. I guess it's something
// like Array<string> or string, but I'm not Angular guy, just guessing.

private lowercaseValidator(c: FormControl): CustomType | null {
    return /[a-z]/g.test(c.value) ? null : { lowercase: this.validationMessages.lowercase };
}

Exemple plus général

type CustomType = { lowercase: Array<string> };

class A {
      private obj: Array<string>;

      constructor() {
            this.obj = Array<string>();
            this.obj.Push("Apple");
            this.obj.Push("bread");
      }

      public testMethod(b: boolean): CustomType | null {
            return b ? null : { lowercase: this.obj };
      }
}

let a = new A();
let customObj: CustomType | null = a.testMethod(false);
// If you're using strictNullChecks, you must write both CustomType and null
// If you're not CustomType is sufficiant
9
Erik Cupal