Delvisa klasser i Typescript. Är det möjligt?
I Angular-källkoden finns en Validators-klass som börjar på följande sätt:
export class Validators {
static min(min: number): ValidatorFn {
return minValidator(min);
}
// ...
}
Är det möjligt att skapa en annan klass i min applikation med samma namn?
export class Validators {
static dark(color: string): ValidatorFn {
return darkValidator(color);
}
// ...
}
Jag skulle vilja använda både min och dark-validatorer med:
Validators.min(2);
Validators.dark('#FFF');
I C# kan jag till exempel använda partial class.
Svar #1
JavaScript har inte partial class och därför har inte heller TypeScript det, eftersom det skulle ha effekt vid körning och därför inte är förenligt med TypeScripts designmål (se TypeScript Design Goal #8, "undvik att lägga till syntax på uttrycksnivå" och TypeScript Design Non-Goal #6, "tillhandahålla ytterligare funktionalitet vid körning"). Det fanns ett förslag om detta i microsoft/TypeScript#563 men det avslogs som utanför omfattningen: en sådan funktion skulle behöva finnas i JavaScript innan TypeScript skulle stödja den.
Istället för partial class kan du använda monkey patching för att lägga till funktionalitet i Validators-klassen från Angular. Just nu verkar du bara fråga om static-metoder. Eftersom static-metoder i princip är samma sak som en egenskap på själva Validators-klassens konstruktor, kan du helt enkelt lägga till en dark-egenskap som gör vad du vill. I JavaScript skulle det se ut så här:
import { Validators } from '@angular/forms';
Validators.dark = function(color) {
return darkValidator(color);
};
Validators.min(2); // okay
Validators.dark('#FFF'); // okay
För att detta ska fungera i TypeScript behöver du göra viss deklarationssammanfogning för att övertyga kompilatorn om att Validators har en statisk dark-metod. Det finns ett öppet förslag på microsoft/TypeScript#2957 för att tillåta ett enklare sätt att göra detta för den statiska sidan av klasser (instanssidan är lite enklare), men för tillfället är den tillgängliga lösningen att deklarera ett namespace med en exporterad variabel som heter dark av rätt typ:
import { Validators, ValidatorFn } from '@angular/forms';
declare module '@angular/forms' {
export namespace Validators {
export let dark: (this: typeof Validators, color: string) => ValidatorFn;
}
}
Validators.dark = function(color: string): ValidatorFn {
return darkValidator(color);
};
Validators.min(2); // okay
Validators.dark('#FFF'); // okay
declare module är modulförstärkning som låter dig lägga till typer till den importerade '@angular/forms'-modulen. Vi har talat om för kompilatorn att det exporterade värdet med namnet Validators är ett namnrym utöver att vara en klasskonstruktör. Detta låter dig tilldela och använda Validators.dark() utan kompilatorvarning.
StackBlitz-länk till kod
