Expresia de tip 'string' nu poate fi folosită pentru a indexa tipul '{}' în TypeScript
Sunt nou în TypeScript. Încerc doar să scriu câteva funcții cloud pentru proiectul meu Firebase. Într-una dintre cerințele mele, trebuie să convertesc un array într-un obiect. Încerc această tehnică pentru a realiza asta:
let msg = {
text : 'hi'
time : 123456789
}
let userIds = ['user1', 'user2']
let updateObj = userIds.reduce((obj, userId) => {
obj[userId + '/messages'] = msg
return obj
}, {})
Ceea ce vreau să fie updateObj este:
{
'user1/messages' : {
'text' : 'hi'
'time' : 123456789
}
'user2/messages' : {
'text' : 'hi'
'time' : 123456789
}
}
Dar nu știu de ce îmi dă această eroare:
src/index.ts:47:6 - error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.
No index signature with a parameter of type 'string' was found on type '{}'.
47 obj[userId + '/messages'] = msg
Răspuns #1
Ai mai multe moduri de a rezolva asta. Problema este că obiectul gol nu acceptă chei arbitrare.
Prima opțiune este să tastezi funcția reduce ca Record<string, typeof msg>, ceea ce ți-ar permite să atribui valoarea msg oricărei chei a acelui obiect. Aceasta ar fi cea mai ușoară și mai slabă (din punctul de vedere al siguranței tipurilor) soluție.
O altă opțiune ar fi să folosești șiruri de șablon ca și cheie dacă folosești o versiune mai nouă de TypeScript și vrei să te asiguri că toate cheile sunt exact în forma {string}\messages. Pentru a realiza asta, tastează reduce ca Record<``$ {string}\messages``, typeof msg>.
A treia opțiune ar fi cea mai strict tipizată, unde poți impune ca cheile să fie exact așa cum sunt în rezultat, tipizând astfel: Record<``$ {typeof userIds[number]}\messages``, typeof msg>. Pentru ca acest lucru să funcționeze, ar trebui de asemenea să specifici userIds cu as const, astfel încât tipul să fie exact ['user1', 'user2'] și nu string[].
Aceste soluții se aplică exact întrebării tale, așa că presupun că în codul real nu ai utilizatorii sau msg static. Deci, dacă users este un array de stringuri pe care îl obții din API, a doua opțiune este cea mai bună, iar dacă obiectul msg din exemplu poate avea diferite semnături, folosește pur și simplu tipul acelui obiect sau pur și simplu folosește unknown dacă vrei să permiți orice valoare.