Search code examples
reactjstypescriptreact-typescripttsx

How to use fix error "does not exist on type string | interface" or can I use satisfies in a useState?


I have the next interfaces

interface ICustomImage {
  data: string;
  width: number;
  height: number;
}

type UserImage = string | ICustomImage

interface IUser {
  id: number;
  firstName: string;
  lastName: string;
  image: UserImage
}

And I'm getting the IUser from an API and storing it in a useState like this:

const [user, setUser] = useState<IUser[]>();

But when I try to use the autocomplete this happens instead of showing all methods that a string have or ICustomImage properties

enter image description here

user.image.width //Because I know it comes with width, this error appears

Property 'width' does not exist on type 'string | ICustomImage'. Property 'width' does not exist on type 'string'.

How can I fix this, or make it so that I can use the following

user.image.data or user.image.width or user.image.height

Solution

  • Typescript is complaining because user.image can be of type string, so you can't access the width property. You'll need to use the in Keyword to check for types in TypeScript.

    if ("width" in user.image) {
        const width = user.image.width; // should be ok
    }
    

    As you'll have to check multiple properties (height, data, etc) you can define a type guard function.

    If you're absolutely sure it'll be of type ICustomImage then you can cast the value as follow :

    const image = user.image as ICustomImage
    const width = image.width;
    

    Regarding your state name, it should be plurals (because it's an array of user).

    // Multiple users
    const [users, setUsers] = useState<IUser[]>();
    // Single user
    const [user, setUser] = useState<IUser>();