You can define a React functional component's types in TypeScript with this:
export const Component: React.FC = () => {
return // Stuff
};
How do you do the same for a non-arrow function?
function Component() {
return // Stuff
}
Is there any practice difference? This popular cheat sheet doesn't cover it so I'm wondering if there's a reason not to use that syntax?
https://github.com/typescript-cheatsheets/react-typescript-cheatsheet
If you want to use the full type of a function to type a non-arrow function, you can use something like this (typescript documentation) :
let myAdd: (x: number, y: number) => number =
function(x: number, y: number): number { return x + y; };
In your case:
const MyComponent: React.FC = function() {
return <div></div>;
};
How do you do the same for a non-arrow function?
import * as React from 'react';
function NonFatArrow(): React.ReactElement {
return (
<>
Non-fat-arrow function
</>
);
}
const FatArrow: React.FunctionComponent = _props => {
return (
<section>
<NonFatArrow/>
</section>
);
};
Is there any practice difference?
Stepping aside from React and Typescript, in ES6 a fat arrow function captures few things including this
and will carry the capture along self. So if there are thousands of such functions then there will be overhead of captures.
Coming back to React and Typescript, this
is not used in React.FunctionComponent(s) however if Typescript transpiler of your choosing transpiles to ES6 then there will be fat arrow functions with captures.
So it all depends on the chosen transpiler and its settings. With Typescript compiler, if you have "target": "es5"
in tsconfig.json, then the FatArrow
component will be transpiled into ES5 function
. Changing the setting to "target": "es6"
ensures FatArrow
is transpiled to an arrow function. With Babel as transpiler your mileage may vary.
There is better type support for some certain cases when you declare component with const
. To understand these cases you can have a look at the React.FC
type:
type FC<P = {}> = FunctionComponent<P>;
interface FunctionComponent<P = {}> {
(props: PropsWithChildren<P>, context?: any): ReactElement | null;
propTypes?: WeakValidationMap<P>;
contextTypes?: ValidationMap<any>;
defaultProps?: Partial<P>;
displayName?: string;
}
Since react component (even function component) is a bit more than just a plain function - specifying precise type for component itself gives you better type inference:
function FooAsFunc({ children }) { // children has 'any' type
return 1234
}
const FooAsConst: React.FC = ({ children }) => {
return 1234 // type error: typescript knows that 1234 is not valid react component return type
}
FooAsFunc.displayName = new Date()
FooAsConst.displayName = new Date() // type error: 'displayName' suppose to be of a type string
In the end, same type safety can be achieved with function
declaration as well, but it just requires more code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With