If you know how to fix the issue, make a pull request instead.
@types/react-select package and had problems.Definitions by: in index.d.ts) so they can respond.Hi,
Because of line 54 at Select.d.ts anything can be passed to select and typescript will not show any errors.
export type SelectComponentsProps = { [key in string]: any };
What is the purpose of that { [key in string]: any }; in Select types?
The thing is that if interface extends { [key in string]: any }; you can pass literally everything to that component. It somehow solves an issue with having custom props in select components but it has a lot of disadvantages, e.g. you can pass everything (even if you make typo typescript will not inform you) and intelisense is not working.
So, I've prepared a solution with a generic argument that can be used for custom props of select components (and is by default set to { [key in string]: any };).
If you don't pass second generic argument you can have any props in custom component just like now:

If you pass an interface as second argument you can have type on that custom prop:

This one caused problems for me too, because I've made some wrapper components around React-Select, that override some props, and pass other props through. So I have a props definition that did that by using some helper types based on Pick and Extract. It looks something like this:
import { Props as ReactSelectProps } from 'react-select/lib/Select';
// Omit: Create a type that has all the keys of T except those named in K
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
// Merge: Create a type that combines types M and N, but where N has a field
// with the same name as M, use only N's definition of that field.
type Merge<M, N> = Omit<M, Extract<keyof M, keyof N>> & N;
// My wrapper component's props can't just `extend` ReactSelectProps, because
// the types for `value` and `onChange` are incompatible.
type WrappedSelectProps = Merge<ReactSeletProps, {
name: string;
value?: number;
options: Array<{value: number, label: React.ReactNode}>,
onChange: (selection?: number) => void;
}>;
This worked great before, but now it fails to provide any validation or Intellisense of the props to pass through to React-Select. That's because my utility types use keyof as their base (as many utility types do). And now that the React-Select props extend { [key in string]: any}, doing keyof on it just returns string.
Fortunately I found a workaround for it. You can extract the "known keys" from a mapped type without using keyof via a somewhat confusing mix of mapped types, conditional types, and type inference: https://stackoverflow.com/questions/51954558/how-can-i-remove-a-wider-type-from-a-union-type-without-removing-its-subtypes-in/51955852#51955852
type KnownKeys<T> = {
[K in keyof T]: string extends K ? never : number extends K ? never : K;
} extends { [_ in keyof T]: infer U }
? U
: never;
... still, it would be more convenient to just be able to use normal utility types like Pick and Extract. For my purposes (writing types that are based on the React-Select props) it would be enough if the defined props of the Select component were just defined as a separate exported type (sort of like SelectComponentsProps is):
export type SelectComponentsProps = { [key in string]: any };
export interface NamedProps<OptionType> {
/* Aria label (for assistive tech) */
'aria-label'?: string;
/* Focus the control when it is mounted */
autoFocus?: boolean;
// ... etc
}
export type Props<OptionType = { label: string; value: string }> = NamedProps<
OptionType
> &
SelectComponentsProps;
Similar problem to @agwells 鈥撀爀xtending { [key in string]: any } seems to break helpers like Omit/Pick/Extract that are necessary for creating wrapper components. Here's a minimal reproduction of the issue in TS playground.
Agree with the above recommendations to export the props separately (assuming extending { [key in string]: any } cannot be removed). In the meantime I've successfully used @agwells workaround like so:
import ReactSelect from 'react-select';
type KnownKeys<T> = {
[K in keyof T]: string extends K ? never : number extends K ? never : K
} extends {[_ in keyof T]: infer U}
? U
: never;
export type CustomSelectProps<T> = Pick<
ReactSelect<T>['props'],
KnownKeys<ReactSelect<T>['props']>
>;
Most helpful comment
This one caused problems for me too, because I've made some wrapper components around React-Select, that override some props, and pass other props through. So I have a props definition that did that by using some helper types based on
PickandExtract. It looks something like this:This worked great before, but now it fails to provide any validation or Intellisense of the props to pass through to React-Select. That's because my utility types use
keyofas their base (as many utility types do). And now that the React-Select props extend{ [key in string]: any}, doingkeyofon it just returnsstring.Fortunately I found a workaround for it. You can extract the "known keys" from a mapped type without using
keyofvia a somewhat confusing mix of mapped types, conditional types, and type inference: https://stackoverflow.com/questions/51954558/how-can-i-remove-a-wider-type-from-a-union-type-without-removing-its-subtypes-in/51955852#51955852... still, it would be more convenient to just be able to use normal utility types like
PickandExtract. For my purposes (writing types that are based on the React-Select props) it would be enough if the defined props of theSelectcomponent were just defined as a separate exported type (sort of likeSelectComponentsPropsis):