angular - TypeScript lägg till överbelastning till metod i en annan definitionsfil
Givet en klass definierad i en tredjeparts d.ts-definitionsfil som jag inte kan redigera:
export declare class MyClass {
someMethod(a: any, b: any);
moreMethods();
// lots more methods here
}
Metoden someMethod kräver en viss typ för parametern b baserat på typen av parametern a. Dock representerar definitionsfilen inte den begränsningen utan båda är any.
Är det möjligt att lägga till överlagringsdefinitioner för someMethod i min egen d.ts - utan att behöva omdefiniera ALLA metoder/egenskaper på den ursprungliga definitionen? Jag vet att det kan göras enkelt om klassen istället var ett gränssnitt.
Något sådant här:
export declare class MyClass {
// add override declaration to ensure `b` is a string if `a` is a number.
someMethod(a: number, b: string);
}
Ovanstående verkar ersätta den ursprungliga klassdefinitionen, vilket betyder att den nu endast har min överskrivna metod i sig, inte moreMethods() etc.
I verkligheten relaterar denna fråga till Angular-komponenten MatDialog som definierar open som:
open<T, D = any, R = any>(
componentOrTemplateRef: ComponentType<T> | TemplateRef<T>,
config?: MatDialogConfig<D>): MatDialogRef<T, R>;
vilket betyder att jag kan instansiera en dialog, men skicka in fel dialogdataobjekt (typ D). Jag skulle vilja lägga till definitioner som:
// ensure that FooDialogComponent is passed FooDialogData for config
open<T, D = any, R = any>(
componentOrTemplateRef: typeof FooDialogComponent,
config?: MatDialogConfig<FooDialogData>): MatDialogRef<T, R>;
// ensure that BarDialogComponent is passed BarDialogData for config
open<T, D = any, R = any>(
componentOrTemplateRef: typeof BarDialogComponent,
config?: MatDialogConfig<BarDialogData>): MatDialogRef<T, R>;
UPPDATERING Så efter @hackape:s svar skapade jag denna kod (https://www.typescriptlang.org/play/index.html#code/KYDwDg9gTgLgBAWwgEwK4BthwLIE9soZYDeAUHHKJLHAMboCGAzk3ACrBPxkUULAwAFigAUDAFxwGAO1wBKOMTgBfcrxkQhwKNgHDkYyTPmKVas6tJVo8ZMHoMoWRIUw58rkmus0AltJhtADMGWiwOLkVzOAB6GLgIADdtdAgGZDgAd18hOCYwe18g31o4GFwC6P4hUQk4aVQEACNtOUlEiF9kAG41VUtSRMcpAEY4AF564Ez3AjRMADoImBE5Xri4f0D0dF8mYGl9hKCg7VYmzUE4QW0scTlSBhGF6v0RACYRgGY1x+eNLQ6PSiEZrIA) som fungerar som förväntat.
Men, som tidigare nämnts använde jag detta för att lägga till överlagringar till Angular Mat Dialog-komponenten, och det verkar inte fungera med det.
declare module '@angular/material/dialog' {
export interface MatDialog {
someTestMethod(): void;
}
}
Var som helst som använder dialogkomponenten nu kommer endast att se someTestMethod() och inte alla befintliga metoder i MatDialog-klassen definierade i Angular-komponenten. Finns det någon skillnad eftersom det läggs till i ett externt npm-modul?
Svar #1
I TS skapar deklaration av class också ett gränssnitt med samma namn, så i teorin kan du utöka MyClass.open-signaturen från utsidan genom tekniken för att slå ihop gränssnitt.
declare module 'existing-module' {
interface MyClass {
someMethod(a: number, b: string): void;
}
}
Men detta kommer inte att lösa ditt problem. Sammanfogning av gränssnitt kan endast lägga till befintlig signatur, du kan överbelasta .open()-metoden, men aldrig åsidosätta den.
Den befintliga .open()-signaturen är redan för lös. Även om du kan överbelasta den med en striktare signatur, kommer allt som bryter mot begränsningen att falla tillbaka på den befintliga lösa signaturen, vilket därmed ogiltigförklarar begränsningen och inte ger något fel.
