En TypeScript, ¿cómo establecer la firma de índice de un objeto que es propiedad de una clase?
Aquí hay una clase:
export class Survey {
isCompleted: boolean;
response: {
'devices': string[];
'languages': string[];
'frameworks': string[];
'backend': string[];
};
}
Estoy recibiendo el error "Elemento tiene implícitamente un tipo 'any' porque el tipo '...' no tiene una firma de índice" al intentar lo siguiente:
return Object.keys(user1.response).map(key => {
return percentageMatch(user1.response[key], user2.response[key]) * categoryScores[key];
})
user1 y user2 son instancias de la clase Survey.
Sé cómo establecer una firma de índice con literales de objeto simples, pero ¿cómo lo hago con las propiedades del objeto response, que a su vez es una propiedad de la clase Survey?
Respuesta #1
Eso requería añadir un tipo de índice [key: string]: string[] al tipo response:
export class Survey {
isCompleted: boolean;
response: {
[key: string]: string[],
devices: string[],
languages: string[],
frameworks: string[],
backend: string[],
};
}
Puedes revisarlo en la demostración de TypeScript Playground que creé.
También podrías considerar reducir la repetición aquí y extraer las claves conocidas a un tipo literal de cadena:
type ResponseKeys = 'devices' | 'languages' | 'frameworks' | 'backend';
export class Survey {
isCompleted: boolean;
response: {
[key in ResponseKeys]: string[]
};
}
Respuesta #2
Se requiere una firma de índice porque Object.keys() pierde información de tipo y devuelve arrays de cadenas.
Puedes introducir tu propia función que sea similar a Object.keys(), pero que se declare para devolver un arreglo de claves reales del objeto:
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)[];
}
Entonces, no habrá error en una función que itera sobre las claves de un objeto y accede a otro objeto, si los objetos son del mismo tipo:
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];
})
}
