javascript - TypeScript - ts(7053) : Elementet har implicit typen 'any' eftersom uttryck av typen 'string' inte kan användas som index


I TypeScript deklarerar jag ett gränssnitt så här:

export default interface MyDTO {
    readonly num: string;
    readonly entitle: string;
    readonly trb: string;
    readonly ucr: string;
    readonly dcr: string;
    readonly udm?: string;
    readonly ddm?: string;
}

Med en funktion skulle jag vilja få tillgång till värdet av en egenskap, vars namn finns i en variabel.

private doSomething(dto: MyDTO, property: string): any {
    let label: any;

    if (['dcr', 'ddm'].includes(property)) {
        label = doSomethingElse(dto[property]);
    } else {
        label = dto[property];
    }
    
    return label;
}

Tyvärr ger TypeScript mig följande felmeddelande:

Element har implicit typen 'any' eftersom ett uttryck av typen 'string' inte kan användas för att indexera typen 'MyDTO'. Ingen indexsignatur med en parameter av typen 'string' hittades på typen 'MyDTO'.ts(7053)

Någon som har en idé, snälla?

Tack

Svar #1

Anledningen till detta är att MyDTO har uttryckligen namngivna egenskaper, men du använder en generell sträng som index, så TypeScript säger att det inte kan garantera att vilken sträng som än skickas in i din doSomething-funktion faktiskt kommer att matcha ett egenskapsnamn på ditt gränssnitt.

En utmärkt lösning för detta som introducerades i TypeScript 2.1 är keyof. Detta låter dig uttryckligen ange typ för något som en nyckel i en viss klass/gränssnitt.

Detta kommer A. att bli av med TS-felet du ser, och B. också kontrollera att alla som anropar din funktion faktiskt skickar en giltig nyckel.

export default interface MyDTO {
    readonly num: string;
    readonly entitle: string;
    readonly trb: string;
    readonly ucr: string;
    readonly dcr: string;
    readonly udm?: string;
    readonly ddm?: string;
}

function doSomething(dto: MyDTO, property: keyof MyDTO): any {
    let label: any;

    if (['dcr', 'ddm'].includes(property)) {
        label = doSomethingElse(dto[property]);
    } else {
        label = dto[property];
    }
    
    return label;
}

doSomething(obj, "foo") // is a TS error
doSomething(obj, "num") // is valid

Relaterade artiklar