0
votes

I have some React+TypeScript code that makes use of a component from a third party library.

<ThirdPartyComponent onSelect={(value: any) => {...}} />

eslint-typescript is identifying this as an issue:

Unexpected any. Specify a different type. eslint(@typescript-eslint/no-explicit-any)

The type definition of the select handler uses any:

export interface ThirdPartySelectCallback extends React.EventHandler<any> {
  (value: any, e: React.SyntheticEvent<{}>): void;
}

What is the proper way to avoid this issue without disabling the eslint rule?


Changing the type to string gives a different error:

<ThirdPartyComponent onSelect={(value: string, e: React.SyntheticEvent<{}>) => {...}} />

Type '(value: string, e: SyntheticEvent<{}, Event>) => void' is not assignable to type 'ThirdPartySelectCallback'

1
Can't you just assume the type you expect? Or is the item type random? - Silvermind
How about onSelect={(value: string) ? Or just add // eslint:disable-line because you cannot control a third party component - user6269864
Assuming a narrower type gives a different error. I updated the question with the details. - Ares

1 Answers

1
votes

You can use ThirdPartyComponent like this:

// add the 2nd parameter e?: React.SyntheticEvent<{}>
const App = () => (
  <ThirdPartyComponent
    onSelect={(v: string, e?: React.SyntheticEvent<{}>) => {}}
  />
)

const ThirdPartyComponent = (props: { onSelect: ThirdPartySelectCallback }) => (
  <div>Hello package</div>
)

Some explanation

React.EventHandler<any> as well as ThirdPartySelectCallback are function type interfaces. When one function interface extends another, for each function parameter the union of the types is formed (because function types are contravariant in their parameters). Have a look at this Playground for an easy example of this merging.

So let's take your example again:

// React.EventHandler - eased up a bit here
type EventHandler<E extends SyntheticEvent<any>> = (event: E): void 

interface ThirdPartySelectCallback extends React.EventHandler<any> {
  (value: any, e: React.SyntheticEvent<{}>): void;
}
  • First parameters are E and any. E | any becomes effectively any.
  • Second parameters are undefined (first function has no second parameter) and React.SyntheticEvent<{}>, so its merged to React.SyntheticEvent<{}> | undefined.

So in the end, you can specify the following function for ThirdPartySelectCallback:

(v: any, e?: React.SyntheticEvent<{}>) => void

, where v can be literally of any type like string to solve your eslint error.