Eroare typescript-eslint „Alocare nesigură a unei valori de tip eroare”
La momentul punerii acestei întrebări, „Atribuire nesigură a unei valori de tip eroare” a returnat zero rezultate pe Google, deci pare că merită o întrebare pe SO.
Eroarea este produsă de analizarea următorului cod TypeScript
const map = {
0.1: 'bar',
};
const x = Math.random();
// "ESLint: Unsafe assignment of an error typed value.(@typescript-eslint/no-unsafe-assignment)"
// https://typescript-eslint.io/rules/no-unsafe-assignment/
const s: string = map[x];
console.log(s);
eslintrc constă din această regulă:
{
"rules": {
"@typescript-eslint/no-unsafe-assignment": "error"
}
}
Iată un playground typescript-eslint care arată eroarea.
Ce cauzează ca linterul să afișeze această eroare?
Atribuire nesigură a unei valori de tip eroare. 8:7 - 8:25
La ce anume se referă valoarea tastată „eroare”?
O soluție era să tipizez explicit map ca const map: Record<number, string>, dar aș dori să înțeleg acea valoare tipizată ca „eroare”, deoarece s ar putea fi cel mult atribuit undefined.
Răspuns #1
Dacă primiți această eroare în VSCode, încercați să reporniți serverul ESLint (Cmd-Shift-P „restart eslint”). Nu întotdeauna recunoaște corect noile importuri.
Răspunsul #2
TL;DR: această eroare indică faptul că încerci să atribui o valoare de tip any unei variabile, ceea ce, deși este legal din punct de vedere tehnic în TS, s-ar putea să nu fie ceea ce intenționai să faci, sau și mai rău, este posibil să nu fii conștient că încerci să faci acest lucru. Așadar, ESLint generează o eroare pentru a te notifica despre această atribuire de tip any, în cazul în care nu știai că există.
Tipul lui const map este dedus din definiția sa - deoarece ai definit map ca un obiect cu o singură cheie predefinită (cea 0.1: "bar"), dar cu posibilitatea de a adăuga chei noi, TS poate deduce tipul doar pentru această cheie (care este string); alte chei potențiale sunt deduse implicit cu tipul any.
Când compilatorul/transpilatorul procesează codul tău, el face, mai mult sau mai puțin, următoarea deducție:
const map={ 0.1: 'bar' };mapeste 100% sigur că are o cheie0.1de tipstring; toate celelalte chei, dacă există, pot fi orice, adică sunt de tipany.
- Nu pot fi 100% sigur că nu au fost adăugate noi câmpuri la
mapîntre declarația sa și utilizarea sa. const x=Math.random();- Nu știu cu exactitate ce valoare conține variabila
x, dar știu că este de tipnumber.
- Nu știu cu exactitate ce valoare conține variabila
const s: string=map[x];- Dezvoltatorul încearcă să acceseze
map[x], dar deoarece nu cunosc valoarea exactăx, pot doar să presupun că orice tip de valoare ar putea fi accesată cu ea (prin urmaremap[x]are tipulany).
- Dezvoltatorul încearcă să acceseze
- Știu 100% că
const seste așteptat să fie de tipstring. - Atribuirea lui
anyunei variabile de tipstringar trebui să fie în regulă, cred.
Aici intervine ESLint, care vede deducția TypeScript și, ca să spunem așa, „declară”: Nu sunt sigur că dezvoltatorul a observat că încearcă să atribuie un any unui string. Prin urmare, voi arunca o eroare pentru a-l notifica despre acest fapt și a-l lăsa să se ocupe de asta în mod explicit.
Dacă după această eroare, schimbi codul pentru a elimina utilizarea any (specificând tipul mai precis), linter-ul și-a făcut treaba. Și chiar dacă doar dezactivezi linter-ul în acel punct, tot și-a făcut treaba, deoarece numai dorea să te facă conștient de problema potențială (și te-ai ocupat de ea).
Deci, cursul corect de acțiune ar fi atât să setezi tipul map la const map: Record<number, string>, cât și să dezactivezi linterul la linia problematică. Deși aș argumenta că prima opțiune este mai de preferat în majoritatea cazurilor.