TypeScript Generic Function Reported As JSX Error
Tags: typescript, computerscience
Published: 2021-06-01 11:59:52

## Motivation
```typescript
const genericFn = <T>() => {
    return "This is a poorly written example generic function"
}
```

Above is an example of a function with a generic parameter `T` that could potentially be used within the function body. However, if the above code is saved in a `.tsx` file (In my context, within a React application, while trying to create a generic custom hook), you will receive with the following error when hover over  `<T>`:
```
JSX element 'T' has no corresponding closing tag.ts(17008)
Cannot find name 'T'.ts(2304)
```

---

## Exploration
### Defining generic function in TypeScript
To resolve the issue, I started with researching on how to properly define a generic function in TypeScript. Perhaps I made a mistake somewhere in the above syntax. I landed on two articles [here](https://www.codementor.io/@jesselangford472/building-reusable-react-hooks-with-generics-1getknj927) and [here](https://medium.com/ableneo/typing-of-react-hooks-in-typescript-947b200fa0b0). Both of  them talked about how to create a custom React hook that uses generics. However, the syntax used in the articles were similar to the above example but no errors were discussed.

While I did not find an answer after heading over to [TypeScript-CheatSheets](https://github.com/typescript-cheatsheets/react#custom-hooks), I thought the note on avoiding type inference when declaring custom hook was an interesting point that I did not know about.
>If you are returning an array in your Custom Hook, you will want to avoid type inference as TypeScript will infer a union type (when you actually want different types in each position of the array). Instead, use [TS 3.4 const assertions](https://devblogs.microsoft.com/typescript/announcing-typescript-3-4/#const-assertions):
```typescript
export function useLoading() {
  const [isLoading, setState] = React.useState(false);
  const load = (aPromise: Promise<any>) => {
    setState(true);
    return aPromise.finally(() => setState(false));
  };
  return [isLoading, load] as const; // infers [boolean, typeof load] instead of (boolean | typeof load)[]
}
```
>This way, when you destructure you actually get the right types based on destructure position.

Credit: [TypeScript-CheatSheets](https://github.com/typescript-cheatsheets/react#custom-hooks)

---

### Google the error
Moving on with the second strategy: "Google & Stack overflow". Searching the above error landed me on the following [issue](https://github.com/microsoft/TypeScript/issues/15713) in the Microsoft TypeScript repository. There were a few more interesting links [here](https://stackoverflow.com/questions/32308370/what-is-the-syntax-for-typescript-arrow-functions-with-generics) and [here](https://basarat.gitbook.io/typescript/type-system/generics). 

So according to the reported issue:

>The usage of `<T>` prior to the function braces causes a JSX error within `.tsx` files: "JSX element has no corresponding closing tag.". Basic example works as expected in a `.ts` file.


The issue was claimed to be a limitation and there were a few workarounds mentioned (in the thread and also in the related stack overflow post):
- change from `.tsx` to `.ts`
- add a comma: `const f = <T,>(arg: T): T => {...}`
- extend this way: `const foo = <T extends unknown>(x: T) => x;`
- or extend this way: `const foo = <T extends {}>(x: T): T => x;`

---

## Thoughts
Funny how issues like this one will continue to bite us even way into the future... simply because no one is going to do anything about it?