typescript returtyp för instansmetod


hur kan jag härleda returtypen för en instansmetod i en utökande klass? se pseudokod nedan

Observera, detta kanske inte är möjligt efter att ha tittat på:

  • https://github.com/microsoft/TypeScript/issues/5863
  • https://github.com/Microsoft/TypeScript/issues/24364
  • Mellankommande lösning för att komma åt klass typargument i statisk metod i Typescript
// Factory.ts
export default class Factory {
  static make(...params: any[]): FactorySubclass["make"] {
    // @ts-ignore
    return new this(...params).make();
  }

  make() {
    throw new Error("Not implemented");
  }
}

// CarFactory.ts
class CarFactory extends Factory {
  make() {
    return "hello";
  }
}

const instance = CarFactory.make(); // should infer "hello"

Svar #1

Ingen anledning till instanceof.

I ett exekveringssammanhang avser Factory['make'] make-egenskapen hos Factory-klassen, vilket i det här fallet är den statiska metoden make(). I ett typ-sammanhang hänvisar dock Factory['make'] till make-egenskapen hos Factory typen, vilket i det här fallet är instansmetoden make().

Så, detta kommer att fungera enligt dina krav:

class Factory {
  static make(...params: any[]): ReturnType<Factory['make']> {
    return new this(...params).make();
  }

  make() {
    throw new Error("Not implemented");
  }
}

const x = Factory.make(); // correctly infers the type of x as "void"

TypeScript 2.1-utgivningsanteckningarna hänvisar till denna notation som indexed access types eller lookup types.

type m = Factory['make']; // defines the type m as "() => void"

Uppdatera

För den uppdaterade frågan, för att få returtypen av make()-metoden i en utökande klass att härledas korrekt, kan du göra det genom att använda en generisk parameter för att referera till klassens typkonstruktör (se här), och säkerställa att basklassens make()-instansmetods returtyp är kompatibel med den implementerande klassens, till exempel genom att låta den returnera any:

class Factory {
  static make<T extends Factory>(
    this: { new (...params: any[]): T },
    ...params: any[]
  ): ReturnType<T['make']> {
    return new this(...params).make();
  }

  make(): any {
    throw new Error('Not implemented');
  }
}

class CarFactory extends Factory {
  make() {
    return 'hello';
  }
}

const x = Factory.make(); // infers the type of x as "any"
const y = CarFactory.make(); // infers the type of y as "string"

Relaterade artiklar