I TypeScript, hur ställer man in indexsignaturen för ett objekt som är en egenskap i en klass?
Här är en klass:
export class Survey {
isCompleted: boolean;
response: {
'devices': string[];
'languages': string[];
'frameworks': string[];
'backend': string[];
};
}
Jag får felet "Elementet har implicit typen 'any' eftersom typen '...' inte har någon indexsignatur" när jag försöker följande:
return Object.keys(user1.response).map(key => {
return percentageMatch(user1.response[key], user2.response[key]) * categoryScores[key];
})
user1 och user2 är instanser av Survey-klassen.
Jag vet hur man ställer in en indexsignatur med enkla objektliteraler, men hur gör jag det med egenskaperna hos response-objektet, som i sig är en egenskap hos Survey-klassen.
Svar #1
Det krävdes att lägga till en indextyp [key: string]: string[] till response-typen:
export class Survey {
isCompleted: boolean;
response: {
[key: string]: string[],
devices: string[],
languages: string[],
frameworks: string[],
backend: string[],
};
}
Du kan kolla på det i TypeScript Playground-demonstrationen som jag skapade.
Du skulle också kunna överväga att minska upprepning här och extrahera kända nycklar till en strängliteraltyp:
type ResponseKeys = 'devices' | 'languages' | 'frameworks' | 'backend';
export class Survey {
isCompleted: boolean;
response: {
[key in ResponseKeys]: string[]
};
}
Svar #2
Indexsignatur krävs eftersom Object.keys() förlorar typinformation och returnerar strängarrayer.
Du kan introducera din egen funktion som liknar Object.keys() men som är deklarerad för att returnera en array med faktiska objekt-nycklar:
function typedKeys<T>(o: T): (keyof T)[] {
// type cast should be safe because that's what really Object.keys() does
return Object.keys(o) as (keyof T)[];
}
Då kommer det inte att bli något fel i en funktion som itererar nycklarna i ett objekt och får åtkomst till ett annat objekt, om objekten är av samma typ:
export class Survey {
isCompleted: boolean;
response: {
'devices': string[];
'languages': string[];
'frameworks': string[];
'backend': string[];
};
}
function f(user1: Survey, user2: Survey) {
return typedKeys(user1.response).map(key => {
return user1.response[key] == user2.response[key];
})
}
