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:

  1. const map={ 0.1: 'bar' };

    • map este 100% sigur că are o cheie 0.1 de tip string; toate celelalte chei, dacă există, pot fi orice, adică sunt de tip any.
    • Nu pot fi 100% sigur că nu au fost adăugate noi câmpuri la map între declarația sa și utilizarea sa.
  2. const x=Math.random();

    • Nu știu cu exactitate ce valoare conține variabila x, dar știu că este de tip number.
  3. 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 urmare map[x] are tipul any).
    • Știu 100% că const s este așteptat să fie de tip string.
    • Atribuirea lui any unei variabile de tip string ar 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.