How to form a TypeScript rule/config that errors if I don't return a JSX in React Functional Component

Viewed 445

I've made the mistake multiple times where I forget to return a JSX from a functional component. That is, I do something like the following:

const Hello = function Hello({name}) {
  <div>Hello  {name}</div>
}

Instead of

const Hello = function Hello({name}) {
  return <div>Hello  {name}</div>
}

I totally know why it's wrong, but I often conflate the the ES6 syntax that does not need a return mentioned with this.

Is there any help TypeScript can give me so I see it as an error before I run it and get the error saying a return is likely missing?

Here is a stackblitz of the problem:

https://stackblitz.com/edit/react-ts-badreturn?file=Hello.tsx

2 Answers

There are several options. The best one is to annotate the constant with React.FunctionComponent<P> type.

import * as React from 'react';

const Hello: React.FunctionComponent<{ name: string }> = function Hello({name}) { // error  Type 'void' is not assignable to type 'ReactElement<any>'
    <div>Hello  {name}</div> 
}

Another option is to just specify the return type of the function

import * as React from 'react';

const Hello = function Hello({name}) : React.ReactElement<any> { // error  Type 'void' is not assignable to type 'ReactElement<any>'
    <div>Hello  {name}</div> 
}
// arrow function 
const Hello = ({name}) : React.ReactElement<any> => { // error  Type 'void' is not assignable to type 'ReactElement<any>'
    <div>Hello  {name}</div> 
}

Note Even without any of these annotations typescript will still help, it will report an error if you try to use the mistaken version of Hello in tsx.

Edit

Another option is to use tslint with the no-unused-expression rule turned on. This rule will ensure that:

Unused expressions are expression statements which are not assignments or function calls (and thus usually no-ops).

This will cover the case when you create a jsx element and do nothing with it.

Add type checking for props.

import React from 'react';

const Hello = function Hello(props: {name: string}) {
  <div>Hello  {props.name}</div>
}

export default Hello;

you will get following error

Error in 0.8.16/lib/invariant.js (42:15)
Hello(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.
Related