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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.