AngularJS TypeScript-tjänstfel


Jag får detta fel när jag försöker lägga till en tjänst i en modul. Kan någon hjälpa till att påpeka vad som är fel?

Angular 1.5.11 och TypeScript 2.2.2

ERROR in ./source/mainModule.ts
(185,33): error TS2345: Argument of type 'typeof AwesomeService ' is not 
assignable to parameter of type 'Injectable<Function>'.
Type 'typeof AwesomeService ' is not assignable to type '(string | Function)[]'.
Property 'push' is missing in type 'typeof AwesomeService '.

Här är där jag försöker lägga till tjänsten

export default angular.module('iris.service', [])
    /* This line throws the error --> */.service('awesomeService', AwesomeService);

I en separat fil, här är hur jag skapar tjänsten

export class AwesomeService extends OtherClass {

    private static $inject = ['configService'];

    constructor() {
        super();
    }
}

uppdatering :

Jag ser att om jag ändrar AwesomeService till en funktion och exporterar den, fungerar det bra. Finns det något sätt jag kan använda en klass för en Service? Det ser ut som att @types/angular specificerar att det andra argumentet till angular.module.service ska vara antingen en sträng eller en funktion.

Svar #1

Ja, du kan göra exakt vad du vill, du behöver bara skriva mindre kod.

Typdeklarationen i @types/angular inkluderar följande

declare global {
    interface Function {
        $inject?: ReadonlyArray<string>;
    }
}

Detta utökar deklarationen av Function-typen. Genom att lägga till en valfri egenskap, $inject, möjliggörs det att rena, lättlästa AngularJS DI-annoteringar kan läggas till klasser och funktioner på ett typ-säkert och deklarativt sätt utan behov av fula typkonverteringar.

Observera att alla klasser och funktioner faktiskt är funktioner.

Problemet med din klass är att, medan typförstärkningen Function ovan anger att $inject är valfri, så anger den inte att när den anges kan den vara private.

Faktiskt är det mycket inte privat, semantiskt sett, eftersom det läses av AngularJS-ramverket och potentiellt andra verktyg också.

För att lösa problemet, skriv helt enkelt

export class AwesomeService extends OtherClass {

    static $inject = ['configService']; // no private here.

    constructor() {
        super();
    }
}

Det mer detaljerade svaret är att två typer anses vara strukturellt inkompatibla om den ena deklarerar ett privat medlem (för att göra detta måste det vara en klass) med samma namn som ett offentligt medlem i den andra (alla gränssnittsmedlemmar är offentliga).

Tyvärr är felet lite kryptiskt. Deklarationen private $inject får typkontrollen att omedelbart ta bort överlagringen av service som tar ett värde av typen Function. Den försöker sedan överlagringen av service som tar ett värde av typen Array och misslyckas.