Home > Blockchain >  TypeScript 4.6.4 is indicating that this code is not valid
TypeScript 4.6.4 is indicating that this code is not valid

Time:09-21

How do I resolve this Typescript issue?

const userData: {
      email: string;
      id: string;
      _token: string;
      _tokenExpirationDate: string;
    } = JSON.parse(localStorage.getItem('userData'));

enter image description here

Message from Console

Error: src/app/auth/authservice.ts:56:20 - error TS2345: Argument of type 'string | null' is not assignable to parameter of type 'string'.
Type 'null' is not assignable to type 'string'.

I added the // @ts-ignore but WebStorm is complaining that there is an error.

CodePudding user response:

Let's ignore the fact that JSON.parse()'s call signature declaration returns the unsafe any type. I'll just assume that if JSON.parse() returns anything other than null, it will be a value of your expected object type.


It's possible that localStorage.getItem("userData") might be null, and TypeScript thinks that it's a mistake to call JSON.parse(null), since generally the point of JSON.parse() is to parse strings that encode JSON values. Parsing null is therefore a type error, even though JavaScript will not have a runtime error. See What does "all legal JavaScript is legal TypeScript" mean? for more information.

If you're trying to fix it to be more type safe, you should make sure only to pass a string. Perhaps like this:

const retrievedValue = localStorage.getItem('userData');
const userData = retrievedValue ? JSON.parse(retrievedValue) as {
  email: string;
  id: string;
  _token: string;
  _tokenExpirationDate: string;
} : null;

This compiles without error, and now userData has the type {email: string ... } | null, where the union with the null type reflects that userData might either be a valid object or null.


If you want to be expedient but a little less safe, you could just lie to the compiler about the local storage result and assert that it is not null using the non-null assertion operator (!):

const userData: {
  email: string;
  id: string;
  _token: string;
  _tokenExpirationDate: string;
} | null = JSON.parse(localStorage.getItem('userData')!);

Note that I added the | null manually there, since the compiler can't see that possibility anymore.

Playground link to code

CodePudding user response:

The easiest way to solve your problem IMO is to just do this:

const userData: {
  email: string;
  id: string;
  _token: string;
  _tokenExpirationDate: string;
} = JSON.parse(localStorage.getItem('userData') ?? "null");

Note the nullish coalascing operator (??) requires typescript 3.7


Now in the case that you want your type to reflect the possibility of being null (in case localStorage does not contain 'userData'), then you probably want to use a union type with null:

const userData: {
  email: string;
  id: string;
  _token: string;
  _tokenExpirationDate: string;
} | null = JSON.parse(localStorage.getItem('userData') ?? "null");

At this point, you might as well extract that userData type to an interface:

interface UserData {
  email: string;
  id: string;
  _token: string;
  _tokenExpirationDate: string;
}

const userData: UserData | null = JSON.parse(localStorage.getItem('userData') ?? "null");
  • Related