downshift-js / downshift

🏎 A set of primitives to build simple, flexible, WAI-ARIA compliant React autocomplete, combobox or select dropdown components.

Home Page:http://downshift-js.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

get{Any}Props functions do not play nicely with TypeScript and React Native

kimthompson opened this issue · comments

  • downshift version: v8.2.3
  • node version: v21.5.0
  • npm (or yarn) version: yarn v1.22.21

Relevant code or config

import Downshift from 'downshift';
import React, {useCallback} from 'react';
import {TextInput} from 'react-native';

export default function Combobox() {
  ...
  return (
    <Downshift itemToString={itemToString}>
      {({
        isOpen,
        getToggleButtonProps,
        getLabelProps,
        getMenuProps,
        getInputProps,
        selectedItem,
        highlightedIndex,
        getItemProps,
        inputValue,
        getRootProps,
      }) => (
          ...
          <TextInput style={styles.input} {...getInputProps({placeholder: 'Choose a title'})} />
          ...
        );
      }}
    </Downshift>
  );
}

What you did:

I basically pulled this snack from your docs into my project as a starting point to see if Downshift is the right choice of autocomplete library for us.

What happened:

It works, but our TypeScript compiler is angry, presumably because functions like getInputProps return a number of attributes that do not exist on React Native TextInput objects. A few examples of this that I found in the console are:

  • aria-activedescendant
  • aria-autocomplete
  • aria-controls
  • aria-labelledby

The exact error is:

No overload matches this call.
Overload 1 of 2, '(props: TextInputProps | Readonly): TextInput', gave the following error.
Type '{ onChange?: ChangeEventHandler | undefined; id: string; 'aria-autocomplete': "list"; 'aria-activedescendant': string | undefined; 'aria-controls': string | undefined; ... 8 more ...; style: { ...; }; }' is not assignable to type 'Readonly'.
Types of property 'onBlur' are incompatible.
Type 'FocusEventHandler | undefined' is not assignable to type '((e: NativeSyntheticEvent) => void) | undefined'.
Type 'FocusEventHandler' is not assignable to type '(e: NativeSyntheticEvent) => void'.
Types of parameters 'event' and 'e' are incompatible.
Property 'relatedTarget' is missing in type 'NativeSyntheticEvent' but required in type 'FocusEvent<Element, Element>'.
Overload 2 of 2, '(props: TextInputProps, context: any): TextInput', gave the following error.
Type '{ onChange?: ChangeEventHandler | undefined; id: string; 'aria-autocomplete': "list"; 'aria-activedescendant': string | undefined; 'aria-controls': string | undefined; ... 8 more ...; style: { ...; }; }' is not assignable to type 'Readonly'.
Types of property 'onBlur' are incompatible.
Type 'FocusEventHandler | undefined' is not assignable to type '((e: NativeSyntheticEvent) => void) | undefined'.

Reproduction repository:

https://snack.expo.dev/@kimicalburn/downshift-react-native-typings-issue-example

Problem description:

tl;dr TypeScript is mad when I try to apply any get{Any}Props function to any equivalent React Native component.

Suggested solution:

I saw that you proposed that people also submit fixes for their own issues, and I'm game! Though I won't probably really dig into it until after the new year, and even then I'm going to prioritize simply using this library as-is in our app first and foremost. I saw that your current recommendation is to not use the <Downshift/> component and to use the hooks instead, so I'm going to attempt to revise that example component accordingly.

I plan to pull down a local version of Downshift and see if I can fix the types, perhaps even providing some alternate return for the functions like getInputProps if you're targeting a React Native component. What approach to this would like to see, as the maintainer(s) of this library?

That's another approach I was thinking of! I also just wanted to make sure I wasn't missing anything. It felt more like a workaround than a true fix, so I was unsure. If that's the approach you'd rather React Native users take, fair enough.

^ see above