Concerning Function and best practices
Function in practice has unsufficient type-safety, being the super-type of all functions. You better replace it with a function type - see the "Solutions" section down under.
In above example, Function is not assignable to the more narrow onClick function type, which causes the error at hand (Playground example).
In addition to mentioned issue, here is what TypeScript docs say about Function:
This is an untyped function call and is generally best avoided because of the unsafe any return type. If need to accept an arbitrary function but don’t intend to call it, the type
() => voidis generally safer.
typescript-eslint has discarded Function with the ban-types rule, emitting following message with default configuration (see also here):
The
Functiontype accepts any function-like value. It provides no type safety when calling the function, which can be a common source of bugs. If you are expecting the function to accept certain arguments, you should explicitly define the function shape.
Better solutions
React already comes with built-in event handler-types to handle common events.
For exampleclick (Playground):
type Props = {
onClick: React.MouseEventHandler<HTMLButtonElement>
};
const Submit = ({ onClick }: Props) => <button onClick={onClick}> click </button>
A more general alternative is to use function types as follows:
type Props = {
onClick: (event: React.MouseEvent<HTMLElement>) => void
};
void is more restrictive than any. There is no chance to return a value in the callback by accident, which would be possible with any.
In summary, we embrace typing capabilities of TypeScript instead of using Function or any.
The parameter now is known to be MouseEvent and the return type void, identifying it as a callback.
Related
Typescript: How to define type for a function callback (as any function type, not universal any) used in a method parameter
Answer from ford04 on Stack OverflowConcerning Function and best practices
Function in practice has unsufficient type-safety, being the super-type of all functions. You better replace it with a function type - see the "Solutions" section down under.
In above example, Function is not assignable to the more narrow onClick function type, which causes the error at hand (Playground example).
In addition to mentioned issue, here is what TypeScript docs say about Function:
This is an untyped function call and is generally best avoided because of the unsafe any return type. If need to accept an arbitrary function but don’t intend to call it, the type
() => voidis generally safer.
typescript-eslint has discarded Function with the ban-types rule, emitting following message with default configuration (see also here):
The
Functiontype accepts any function-like value. It provides no type safety when calling the function, which can be a common source of bugs. If you are expecting the function to accept certain arguments, you should explicitly define the function shape.
Better solutions
React already comes with built-in event handler-types to handle common events.
For exampleclick (Playground):
type Props = {
onClick: React.MouseEventHandler<HTMLButtonElement>
};
const Submit = ({ onClick }: Props) => <button onClick={onClick}> click </button>
A more general alternative is to use function types as follows:
type Props = {
onClick: (event: React.MouseEvent<HTMLElement>) => void
};
void is more restrictive than any. There is no chance to return a value in the callback by accident, which would be possible with any.
In summary, we embrace typing capabilities of TypeScript instead of using Function or any.
The parameter now is known to be MouseEvent and the return type void, identifying it as a callback.
Related
Typescript: How to define type for a function callback (as any function type, not universal any) used in a method parameter
You can simply write it like this, which prevents any and is more telling. Especially for custom functions:
Interface Props { onClick: (e: Event) => void; }
This will tell the calling component, what onClick will expect and what the parameters are.
Hope this helps. Happy coding.
Function component props with typescript
React typescript. How can I get props type from a component?
reactjs - TypeScript React: Access component property types - Stack Overflow
. 2018-03-09T10:34:55.263Z+00:00 ... @OliverJosephAsh that's true. If you really need that you can use module augmentation to extend react typings to put dummy type that would allow you to fetch prop types. Look here typescriptlang...
More on stackoverflow.comCan Typescript for React props be terser?
Videos
Hey guys, do you see any disadvantages about writing:
const Component = ({
text
}:{
text: string
}) => {
return (
<div>{text}</div>
)
}instead of:
interface ComponentProps {
text: string
}
const Component = ({text}: ComponentProps) => {
return (
<div>{text}</div>
)
}Hi,all.
I want to defined a Link component that has an as props. For example, using react router link component. <Link as={ReactRouterLink} to="/">Page</> . In this case, even I know the types of react router link, for example to props, but I don't want to define it on the Link. Is there a way to define the types of Link that can extend the type from as component?
2019: noticed all answers above are quite outdated so here is a fresh one.
Lookup type
With newer TS versions you can use lookup types.
type ViewProps = View['props']
Despite being very convenient, that will only work with class components.
React.ComponentProps
The React typedefs ship with an utility to extract the type of the props from any component.
type ViewProps = React.ComponentProps<typeof View>
type InputProps = React.ComponentProps<'input'>
This is a bit more verbose, but unlike the type lookup solution:
- the developer intent is more clear
- this will work with BOTH functional components and class components
All this makes this solution the most future-proof one: if you decide to migrate from classes to hooks, you won't need to refactor any client code.
Starting with TypeScript 2.8, you can use conditional types, e.g. given:
interface MyComponentProps { bar: string; }
declare const MyComponent: React.Component<MyComponentProps>;
interface MyComponentClassProps { bar: string; }
declare const MyComponentClass: React.ComponentClass<MyComponentClassProps>;
interface MyStatelessComponentProps { bar: string; }
declare const MyStatelessComponent: React.StatelessComponent<MyStatelessComponentProps>;
We can define these helpers:
type GetComponentProps<T> = T extends React.ComponentType<infer P> | React.Component<infer P> ? P : never
And use them like so:
// $ExpectType MyComponentProps
type MyComponentPropsExtracted = GetComponentProps<typeof MyComponent>
// $ExpectType MyComponentClassProps
type MyComponentClassPropsExtracted = GetComponentProps<typeof MyComponentClass>
// $ExpectType MyStatelessComponentProps
type MyStatelessComponentPropsExtracted = GetComponentProps<typeof MyStatelessComponent>
Update 2018-12-31: this is now available in the official React typings via React.ComponentProps.