DEV Community

Cover image for Writing React Components with Typescript
Ankit Yadav
Ankit Yadav

Posted on

Writing React Components with Typescript

Typescript and React have been a powerful combination
  • I've found that people are afraid to move to typescript because they think that writing typescript requires a lot of boilerplate.
  • Believe me, i was one of those people. I used to think the same way until i met typescript. I'll agree that at the beginning it was a bit intimidating with all the types and everything but it's fun once you get the hang of it.
  • Once you start using typescript, going back to Javascript feels like you've lost some powerπŸ˜….At least that's what i found in my experience.
  • I want to take out your fear of using typescript with react and help you get started in a way that you don't feel so intimidated.
  • We are going to write a Functional Component using react and typescript.
Functional components with TypeScript
  • You can create functional components in TypeScript just like you would in JavaScript.

  • The main difference is the FC interface, which stands for Function Component. We use this to tell TypeScript that this is a React function component and not just a regular function.

  • Optionally, we can add types for the props by defining an interface and passing it to the generic FC.

  • A functional component then typically looks like this:

import React, { FC } from 'react';

interface TitleProps {
  title: string;
}

const Title: FC<TitleProps> = ({ title, subtitle }) => {
  return (
    <>
      <h1>{title}</h1>
      <h2>{subtitle}</h2>
    </>
  );
};

export default Title;
Enter fullscreen mode Exit fullscreen mode
  • Now, if we go ahead and use this component in our react application, we will get some benefits like
    • code autocompletion
    • compilation errors in our editor that warn us when we forgot a property or use the wrong types.

Type Error

Note
  • Generic types in TypeScript are like functions that accept parameters. Instead of parentheses, generic types use angle brackets (<>).
  • For the FC interface, you don't need to pass any parameters, so you could use it without a generic type by omitting the angle brackets altogether when your component doesn't accept any props:
 const Title: FC = () => {
  // ...
 } 
Enter fullscreen mode Exit fullscreen mode
Optional props
  • Not all of the props that you pass to components are need to be required.
  • We can make a props optional by adding a question mark to the interface:
 interface TitleProps {
  title: string; // required
  subtitle?: string; // optional
 }
Enter fullscreen mode Exit fullscreen mode
  • This will allow you to omit the prop when you don't need it.
Alternatives to the FC interface
  • If you know TypeScript, you might think why I'm not applying the prop interface to the function parameters itself.
const Title = ({ title, subtitle }: TitleProps) => {
  // ...
}
Enter fullscreen mode Exit fullscreen mode
  • this syntax works fine and you can write functions in typescript like this.
  • But, there is a specific reason as to why you want to use a generic type like FC because it comes with all the types that are required by a functional component.
  • this includes the implicit children prop. because this becomes a default prop in any functional component that you define with FC interface, we don't need to add it to our interface.
import React, { FC } from 'react';

interface TitleProps {
  title: string;
  subtitle?: string;
}

const Title: FC<TitleProps> = ({ title, subtitle, children }) => {
  return (
    <>
      <h1>{title}</h1>
      <h2>{subtitle}</h2>
      <div>{children}</div>
    </>
  );
};

export default Title;
Enter fullscreen mode Exit fullscreen mode
  • Sometimes it's a disadvantage because FC interface always adds the children prop, regardless of whether you use it or not.
Type-safe state in function components
  • To have type-safety for the state in functional components, we don't necessarily need to modify our code: The useState hook inherits the type from the value we use to initialise it.
  • If we use a more complex type or don't initialize the state, we can pass the type like the following:
const [title, setTitle] = useState<string>(null); 
Enter fullscreen mode Exit fullscreen mode

Discussion (0)