Downshift: GetInputPropsOptions type definition may be too restrictive

Created on 25 Jan 2018  路  4Comments  路  Source: downshift-js/downshift

https://github.com/paypal/downshift/blob/ae58dab51dafda217818c231001e05ed42f3219e/typings/index.d.ts#L77

Using typescript and was passing custom props with names like classes & startAdornment to getInputProps.

This code ran but resulted in a typescript error bec. those custom props did not fit the definition I linked above.

Seems like defining the options passed as React.HTMLProps<HTMLInputElement> may be too restrictive since it disallows custom props.

Some example code here to demonstrate:

let x: React.HTMLProps<HTMLInputElement>
x = { id: "something" }
x = { custom: "something" }

last line should cause an error

I worked around this by just passing the custom props without using getInputProps but I'm not sure if that's the intention or not.

Let me know if I've missed something and thanks!

TypeScript bug help wanted

Most helpful comment

Hmm... I'm interested to make a pull request on this, but IMO when user has custom props that is not part of standard HTML input props, they should pass it separately, as it wouldn't ever crash with downshift props.
If we're making the props to flexible, I'm afraid that the props typo would not be caught.

All 4 comments

You're right @emp823. The typings should allow you to pass anything in that object (though generally you should only be passing those props to the <input /> element directly, it's understandable that you might be using a component that renders an input and forwards all but some custom props).

I don't maintain the typescript definitions, but several maintainers here do. You should also feel free to make a pull request to fix this :) Thanks!

Hmm... I'm interested to make a pull request on this, but IMO when user has custom props that is not part of standard HTML input props, they should pass it separately, as it wouldn't ever crash with downshift props.
If we're making the props to flexible, I'm afraid that the props typo would not be caught.

Why wouldn't you use generics for this, getInputProps currently returns an any - but we can do better than that as we know most of what it's going to return - and then we can extend that with the generic type of the passed props - as long as your component is typed this should still catch typos

e.g.

// Incomplete list just for demonstration
interface InputProps {
  'aria-autocomplete': 'list';
  'aria-activedescendant': string | null;
  'aria-controls': string | null;
  ...
}

interface PropGetters {
  ...
  getInputProps<T>(extraProps?: T): T & InputProps;
  ...
}

Running into similar problems trying to convert the Material UI searchbox downshift demo to work in Typescript.

<div className={classes.container}>
            {renderInput({
              fullWidth: true,
              classes,
              InputProps: getInputProps({
                startAdornment: selectedItem.map(item => (
                  <Chip
                    key={item}
                    tabIndex={-1}
                    label={item}
                    className={classes.chip}
                    onDelete={this.handleDelete(item)}
                  />
                )),
                onChange: this.handleInputChange,
                onKeyDown: this.handleKeyDown,
                placeholder: "Select multiple countries"
              }),
              label: "Label"
            })}
            {isOpen ? (
              <Paper className={classes.paper} square>
                {getSuggestions(inputValue2).map((suggestion, index) =>
                  renderSuggestion({
                    suggestion,
                    index,
                    itemProps: getItemProps({ item: suggestion.label }),
                    highlightedIndex,
                    selectedItem: selectedItem2
                  })
                )}
              </Paper>
            ) : null}
          </div>

Here getInputProps uses a property startAdornment not in the types for InputProps.
Seems to be an interface limitation problem with GetInputPropsOptions however

getInputProps: (options?: GetInputPropsOptions) => any

export interface GetInputPropsOptions
  extends React.HTMLProps<HTMLInputElement> {
  disabled?: boolean
}

I ended going with the suggestion by @johnjesse to use Generics and it works like a charm

  getInputProps: <T>(options?: T) => T & GetInputPropsOptions;
  getItemProps: (options: GetItemPropsOptions<Item>) => any;
Was this page helpful?
0 / 5 - 0 ratings