5

I'm trying to add TypeScript types to the following code:

const [selectedDevice, setSelectedDevice] = useState<DesktopOrMobile>(DesktopOrMobile.desktop);

const handleChange = (event: React.ChangeEvent<{ value: DesktopOrMobile }>): void => {
  setSelectedDevice(event.target.value);
};

<select value={selectedDevice} onChange={handleChange}>
  <option value={DesktopOrMobile.desktop}>Desktop</option>
  <option value={DesktopOrMobile.mobile}>Mobile</option>
</select>

But I get this error:

TS2322: Type '(event: React.ChangeEvent<{ value: DesktopOrMobile;}>) => void' is not assignable to type '(event: ChangeEvent) => void'.   Types of parameters 'event' and 'event' are incompatible.     Type 'ChangeEvent' is not assignable to type 'ChangeEvent<{ value: DesktopOrMobile; }>'.       Type 'HTMLSelectElement' is not assignable to type '{ value: DesktopOrMobile; }'.         Types of property 'value' are incompatible.           Type 'string' is not assignable to type 'DesktopOrMobile'.

I know that the problem is that event.target.value from the onChange event on the select list has a type of string not DesktopOrMobile but I'm not sure what the best solution is.

UPDATE: I could use an enum but not sure if there's a better way than type casting:

import * as React from "react";
import {useState} from 'react'

enum DesktopOrMobile  {
  mobile  = 'mobile',
  desktop =  'desktop'
}

export default function App() {
  const [selectedDevice, setSelectedDevice] = useState<DesktopOrMobile>(DesktopOrMobile.mobile);
  const handleChange = (value: DesktopOrMobile): void => {
    setSelectedDevice(value);
  };
  return (
      <div>
        <select value={selectedDevice} onChange={e => handleChange(e.target.value as DesktopOrMobile)}>
          <option value={DesktopOrMobile.desktop}>Desktop</option>
          <option value={DesktopOrMobile.mobile}>Mobile</option>
        </select>
      </div>
    );
}
1
  • looks like there is no way to get value of enums as type in typescript. you can use like this: type DesktopOrMobile = 'mobile' | 'desktop'. or use <keyof typeof DesktopOrMobile > if you sure key and value are equal. but this is not a good way. i suggest to use String Literal Type Commented Jan 21, 2021 at 12:31

1 Answer 1

0

EDIT

You cannot assign a type to a state, in this case, you need to declare an object with the keys you need.

Assuming that DesktopOrMobile type is:

type DesktopOrMobile = { 
  mobile: string,
  desktop: string 
}

I think the best idea is to assign the type of value as a keyof DesktopOrMobile, like this:

const DesktopOrMobileObj: DesktopOrMobile = {
  mobile: "mobile",
  desktop: "desktop"
};

type ValueType = DesktopOrMobile[keyof DesktopOrMobile];

const [selectedDevice, setSelectedDevice] = useState<ValueType>(DesktopOrMobileObj.desktop);

const handleChange = (event: React.ChangeEvent<{ value: ValueType }>): void => {
  setSelectedDevice(event.target.value);
};

<select value={selectedDevice} onChange={handleChange}>
  <option value={DesktopOrMobileObj.desktop}>Desktop</option>
  <option value={DesktopOrMobileObj.mobile}>Mobile</option>
</select>

The value of this event is a string, so you must assign a string to it.

By the way, next time paste the type too.

Sign up to request clarification or add additional context in comments.

3 Comments

please test your code before adding in answer.
Sorry guys, I've committed some mistakes up there! I've just fixed that and create a codesandbox:codesandbox.io/s/sweet-dhawan-tm5ve?file=/src/App.tsx

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.