javascript - Hur man undviker att omdeklarera parametrars typer i en klassmetod i en subklass i Typescript
Jag har en subklass som utökar en abstrakt superklass i en annan fil. Koden nedan i implementation.ts misslyckas med TS-typkontrollen för doStrangeThing() eftersom jag måste deklarera om parametertyperna (string,IComplexOptions). Jag hoppas kunna undvika den extra importen och ordrikedomen. Kan någon påpeka hur det kan göras (om möjligt)?
Det verkar intuitivt att kompilatorn borde härleda metodsignaturen från superklassen, särskilt om det är en abstrakt sådan, eller åtminstone ta det som standard om det saknas. Finns det något sätt jag missar för att göra detta (utan att beakta komplikationer som att försöka överbelasta metoder, eller unionstyper), eller åtminstone något sätt att extrahera parametern, eller något sätt att ge kompilatorn en vink om att ärva signaturen från superklassen?
//
// baseClasses.ts
//
import {IComplexOptions} from './foo';
abstract class Animal {
abstract name: string;
abstract doStrangeThing( action:string, options:IComplexOptions ):void;
}
//
// implementation.ts
//
import {Animal} from './baseClasses';
class Rhino extends Animal {
name="Rhino";
doStrangeThing(action,options){ // <== TS error here, implicit 'any'
}
}
Svar #1
Det finns inget sätt att faktiskt undvika att deklarera om argumentens typer eftersom Typescript implementerar strukturellt arv.
Som en lösning kan du använda verktygstypen Parameters för att extrahera parametrarna från ett annat gränssnitt. Detta är användbart när du använder ett enda objekt som en funktionsparameter (jfr positionella parametrar) och du har metoder vars argument kan förändras ofta.
Till exempel:
interface Foo {
method(args: { arg1: string, arg2: number}): void;
}
class Bar implements Foo {
method({ arg1, arg2 }: Parameters<Foo['method']>[0]): void {
// arg1 and arg2 types will be correctly inferred
}
}
Om du har flera metoder för att deklarera om kan du skapa din egen typer för en viss klass:
interface Foo {
method(args: { arg1: string, arg2: number}): void;
}
type FooArgs<Method extends keyof Foo> = Parameters<Foo[Method]>[0];
class Bar implements Foo {
method({ arg1, arg2 }: FooArgs<'method'>): void {
// arg1 and arg2 types will be correctly inferred
}
}
