Background
Trying to get into the spirit of TypeScript, I am writing fully typed signatures in my Components and Services, which extends to my custom validation functions for angular2 forms.
I know that I can overload a function signature, but this requires that the parameters are different for each return type because tsc
compiles each signature to a separate function:
function pickCard(x: {suit: string; card: number; }[]): number;
function pickCard(x: number): {suit: string; card: number; };
function pickCard(x): any { /*common logic*/ };
I also know that I can return a single type (like a Promise) which can itself be of multiple sub-types:
private active(): Promise<void|null> { ... }
However, in the context of angular2 custom form validators, a single signature (one parameter of type FormControl
) can return two distinct types: an Object
with form errors, or null
to indicate the control has no errors.
This, obviously, does not work:
private lowercaseValidator(c: FormControl): null;
private lowercaseValidator(c: FormControl): Object {
return /[a-z]/g.test(c.value) ? null : { lowercase: this.validationMessages.lowercase };
}
Nor do
private lowercaseValidator(c: FormControl): null|Object {...}
private lowercaseValidator(c: FormControl): <null|Object> {...}
(Interestingly, I get the following errors, rather than something more informative:
error TS1110: Type expected.
error TS1005: ':' expected.
error TS1005: ',' expected.
error TS1128: Declaration or statement expected.
)
TL;DR
Am I left simply using
private lowercaseValidator(c: FormControl): any { ... }
which would seem to negate the advantage of having type signatures?
More generally, looking forward to ES6
While this question is inspired by angular2 forms validators, which are handled directly by the framework, so you might not care about declaring the return type, it is still generally-applicable, especially given ES6 constructs like function (a, b, ...others) {}
Perhaps it's simply better practice to avoid writing functions that can return multiple types, but it is rather idiomatic, owing to JavaScript's dynamic nature.
Ok, this is the right way if you want to have proper types:
More general example