One simplest option will be setting a default value for your optional props. As an example, if className is optional you can change your ComponentB.js to something like this.

const ComponentB = ({ children, className="", equalWidth }) => {
  return (...)
}

Also if you deconstruct your props in the function body instead of the signature TS will not complain about typings.

const ComponentB = (props) => {
  const { children, className, equalWidth } = props;
  return (...)
}
Answer from Tharaka Wijebandara on Stack Overflow
Top answer
1 of 2
13

One simplest option will be setting a default value for your optional props. As an example, if className is optional you can change your ComponentB.js to something like this.

const ComponentB = ({ children, className="", equalWidth }) => {
  return (...)
}

Also if you deconstruct your props in the function body instead of the signature TS will not complain about typings.

const ComponentB = (props) => {
  const { children, className, equalWidth } = props;
  return (...)
}
2 of 2
8

Assuming that ComponentB.js is going to end up as a TypeScript component:

interface ComponentBProps {
    children?: ReactNode;
    className?: string;
    equalWidth?: boolean;
}

const ComponentB = ({ children, className, equalWidth }: ComponentBProps) => {
    // 
};

In the special case where all properties are optional, you could remove the ? from each property on the interface and use Partial<ComponentBProps>, but I guess that at least something will end up being a required prop.


If you want to keep ComponentB.js as it is, then an alternative solution is to create a type definitions file:

import { ReactNode, StatelessComponent } from "react";

interface ComponentBProps {
    children?: ReactNode
    className?: string;
    equalWidth?: boolean;
}

export const ComponentB: StatelessComponent<ComponentBProps>;

If you put in this the same directory as the JavaScript file and name is ComponentB.d.ts, then you should be able to import ComponentB in your TypeScript file.

The way I have written the definition assumes that the component is a named export, not the default, i.e. it is exported like export const ComponentB in the .js file.

(probably) working example: https://github.com/fenech/tsx-jsx

Discussions

reactjs - Selectively rendering optional component properties in React JSX - Stack Overflow
3 How to set two properties for a React component as optional depending on another property using TypeScript? More on stackoverflow.com
🌐 stackoverflow.com
How to pass optional elements to a component as a prop in reactjs
I am trying to figure out the proper "react" way to pass in an optional prop that is an Element to a container component, that is handled differently from the children of that component. For a si... More on stackoverflow.com
🌐 stackoverflow.com
reactjs - Default property value in React component using TypeScript - Stack Overflow
Before TypeScript 3.0 implemented compiler support for defaultProps you could still make use of it, and it worked 100% with React at runtime, but since TypeScript only considered props when checking for JSX attributes you'd have to mark props that have defaults as optional with ?. More on stackoverflow.com
🌐 stackoverflow.com
React-Typescript complaining about optional props missing (defined with prop-types)
You need ?: to flag a property as optional. Otherwise you MUST add it, even if you give it the value undefined. There is a difference in checking for the key. interface Foo { requiredProperty: any; optionalProperty?: string; } const someObject: Foo = getFoo(); if ("requiredProperty" in someObject) // always true { // the value may be undefined console.log(someObject.requiredProperty); } if ("optionalProperty" in someObject) { // the value cannot be undefined console.log(someObject.optionalProperty); } // the value may be undefined console.log(someObject.optionalProperty); More on reddit.com
🌐 r/typescript
11
5
May 5, 2022
🌐
DhiWise
dhiwise.com › post › how-react-optional-props-can-improve-the-maintainability
Embracing Optional Props for Robust React Applications
June 14, 2024 - Props can be passed to components ... these, react optional props provide flexibility, allowing components to function without the need for every prop to be passed by the parent component....
🌐
DEV Community
dev.to › lico › i-ruined-my-react-components-by-using-optional-props-3o64
I ruined my React components by using optional props - DEV Community
December 22, 2022 - There were too many options and I wasn't sure what I was going to use to make the component work properly. I also used unexpected default values a lot. It makes plenty of unnecessary defensive code and I couldn't expect what default values it has. I will show you some examples that are similar to the mistakes that I made. Let's say, there is a Button component like below. import { ReactNode } from 'react'; type ButtonType = 'primary' | 'secondary'; interface ButtonProps { children?: ReactNode | string; onClick?: VoidFunction; type?: ButtonType; } const Button = ({ children, onClick, type = 'primary' }: ButtonProps) => { const bgColor = type === 'primary' ?
🌐
LogRocket
blog.logrocket.com › home › a complete guide to react default props
A complete guide to React default props - LogRocket Blog
June 4, 2024 - Cover three ways to implement default props in React and provide default values for props that are not required by the component.
🌐
React TypeScript Cheatsheets
react-typescript-cheatsheet.netlify.app › typing defaultprops
Typing defaultProps | React TypeScript Cheatsheets
For Class components, there are a couple ways to do it (including using the Pick utility type) but the recommendation is to "reverse" the props definition: type GreetProps = typeof Greet.defaultProps & { age: number; }; class Greet extends React.Component<GreetProps> { static defaultProps = { age: 21, }; /*...*/ } // Type-checks! No type assertions needed! let el = <Greet age={3} />; React.JSX.LibraryManagedAttributes nuance for library authors
Find elsewhere
🌐
DEV Community
dev.to › fullstackchris › react-with-typescript-optional-props-with-default-values-33nc
React with TypeScript: Optional Props with Default Values - DEV Community
October 10, 2021 - import * as React from "react"; // Required props interface IFancyTitleRequiredProps { title: string; } // Optional props interface IFancyTitleOptionalProps { color: string; fontSize: number; } // Combine required and optional props to build the full prop interface interface IFancyTitleProps extends IFancyTitleRequiredProps, IFancyTitleOptionalProps {} // Use the optional prop interface to define the default props const defaultProps: IFancyTitleOptionalProps = { color: "red", fontSize: 40, }; // Use the full props within the actual component const FancyTitle = (props: IFancyTitleProps) => { const { title, color, fontSize } = props; return <h1 style={{ color, fontSize }}>{title}</h1>; }; // Be sure to set the default props FancyTitle.defaultProps = defaultProps; export default FancyTitle;
🌐
O'Reilly
oreilly.com › library › view › learn-react-with › 9781789610253 › 37d6aed2-5d7b-4d0e-a4d9-1c8892c83c0b.xhtml
Optional props - Learn React with TypeScript 3 [Book]
November 29, 2018 - We put a ? before the type annotation to denote that the prop is optional. Note also that we don't get a compilation error in App.tsx, where we reference, Confirm because we are not required to enter these as attributes on Confirm. Let's reference these props in our JSX now, ...
Author   Carl Rippon
Published   2018
Pages   502
🌐
React
legacy.reactjs.org › docs › typechecking-with-proptypes.html
Typechecking With PropTypes – React
optionalElement: PropTypes.element, // A React element type (ie. MyComponent). optionalElementType: PropTypes.elementType, // You can also declare that a prop is an instance of a class. This uses // JS's instanceof operator. optionalMessage: PropTypes.instanceOf(Message), // You can ensure that your prop is limited to specific values by treating // it as an enum.
🌐
Meje
meje.dev › blog › optional-props-in-typescript
Optional props in TypeScript
April 24, 2023 - In the snippet above, I'm extending the prowess of ReactSVG by passing the path to where our icons are located with the name prop appended to it, in the string literal.
🌐
Medium
medium.com › @haymap28 › defining-optional-props-with-typescript-in-react-1659673081b2
Defining Optional Props with TypeScript in React | by Michael Adejumo | Medium
February 3, 2023 - Since the “name” prop is now defined as optional in this example, the component will display “Hello, there” instead of the name if it is not passed.
🌐
DEV Community
dev.to › bytebodger › default-props-in-react-typescript-2o5o
Default Props in React/TypeScript - DEV Community
July 29, 2020 - Nothing fancy here. A dead-simple component that accepts up to 5 props, with 2 of those props being required. For the 3 optional props, default values are assigned. If the component is wrapping other content, that content will be rendered with props.children. This is basically React 101.
🌐
Bobby Hadz
bobbyhadz.com › blog › react-optional-props-typescript
Set optional props with default values in React TypeScript | bobbyhadz
To set optional props with default values in React TypeScript, mark the props on the type as optional using a question mark.
🌐
React
legacy.reactjs.org › docs › components-and-props.html
Components and Props – React
To learn more about the reasoning behind this convention, please read JSX In Depth. Components can refer to other components in their output. This lets us use the same component abstraction for any level of detail. A button, a form, a dialog, a screen: in React apps, all those are commonly expressed as components. For example, we can create an App component that renders Welcome many times: function Welcome(props) { return <h1>Hello, {props.name}</h1>; } function App() { return ( <div> <Welcome name="Sara" /> <Welcome name="Cahal" /> <Welcome name="Edite" /> </div> ); }
Top answer
1 of 12
431

Default props with class component

Using static defaultProps is correct. You should also be using interfaces, not classes, for the props and state.

Update 2018/12/1: TypeScript has improved the type-checking related to defaultProps over time. Read on for latest and greatest usage down to older usages and issues.

For TypeScript 3.0 and up

TypeScript specifically added support for defaultProps to make type-checking work how you'd expect. Example:

interface PageProps {
  foo: string;
  bar: string;
}

export class PageComponent extends React.Component<PageProps, {}> {
    public static defaultProps = {
        foo: "default"
    };

    public render(): JSX.Element {
        return (
            <span>Hello, { this.props.foo.toUpperCase() }</span>
        );
    }
}

Which can be rendered and compile without passing a foo attribute:

<PageComponent bar={ "hello" } />

Note that:

  • foo is not marked optional (ie foo?: string) even though it's not required as a JSX attribute. Marking as optional would mean that it could be undefined, but in fact it never will be undefined because defaultProps provides a default value. Think of it similar to how you can mark a function parameter optional, or with a default value, but not both, yet both mean the call doesn't need to specify a value. TypeScript 3.0+ treats defaultProps in a similar way, which is really cool for React users!
  • The defaultProps has no explicit type annotation. Its type is inferred and used by the compiler to determine which JSX attributes are required. You could use defaultProps: Pick<PageProps, "foo"> to ensure defaultProps matches a sub-set of PageProps. More on this caveat is explained here.
  • This requires @types/react version 16.4.11 to work properly.

For TypeScript 2.1 until 3.0

Before TypeScript 3.0 implemented compiler support for defaultProps you could still make use of it, and it worked 100% with React at runtime, but since TypeScript only considered props when checking for JSX attributes you'd have to mark props that have defaults as optional with ?. Example:

interface PageProps {
    foo?: string;
    bar: number;
}

export class PageComponent extends React.Component<PageProps, {}> {
    public static defaultProps: Partial<PageProps> = {
        foo: "default"
    };

    public render(): JSX.Element {
        return (
            <span>Hello, world</span>
        );
    }
}

Note that:

  • It's a good idea to annotate defaultProps with Partial<> so that it type-checks against your props, but you don't have to supply every required property with a default value, which makes no sense since required properties should never need a default.
  • When using strictNullChecks the value of this.props.foo will be possibly undefined and require a non-null assertion (ie this.props.foo!) or type-guard (ie if (this.props.foo) ...) to remove undefined. This is annoying since the default prop value means it actually will never be undefined, but TS didn't understand this flow. That's one of the main reasons TS 3.0 added explicit support for defaultProps.

Before TypeScript 2.1

This works the same but you don't have Partial types, so just omit Partial<> and either supply default values for all required props (even though those defaults will never be used) or omit the explicit type annotation completely.

Default props with Functional Components

You can use defaultProps on function components as well, but you have to type your function to the FunctionComponent (StatelessComponent in @types/react before version 16.7.2) interface so that TypeScript knows about defaultProps on the function:

interface PageProps {
  foo?: string;
  bar: number;
}

const PageComponent: FunctionComponent<PageProps> = (props) => {
  return (
    <span>Hello, {props.foo}, {props.bar}</span>
  );
};

PageComponent.defaultProps = {
  foo: "default"
};

Note that you don't have to use Partial<PageProps> anywhere because FunctionComponent.defaultProps is already specified as a partial in TS 2.1+.

Another nice alternative (this is what I use) is to destructure your props parameters and assign default values directly:

const PageComponent: FunctionComponent<PageProps> = ({foo = "default", bar}) => {
  return (
    <span>Hello, {foo}, {bar}</span>
  );
};

Then you don't need the defaultProps at all! Be aware that if you do provide defaultProps on a function component it will take precedence over default parameter values, because React will always explicitly pass the defaultProps values (so the parameters are never undefined, thus the default parameter is never used.) So you'd use one or the other, not both.

2 of 12
23

With Typescript 2.1+, use Partial < T > instead of making your interface properties optional.

export interface Props {
    obj: Model,
    a: boolean
    b: boolean
}

public static defaultProps: Partial<Props> = {
    a: true
};
🌐
Julesblom
julesblom.com › writing › react-optional-parameters
An Animated Guide to Reacts Optional Parameters | JulesBlom.com
September 6, 2023 - In a way, a reducers parameters are optional. You’re not obliged to use the state or action parameters, a reducer only has to return new state. Ignoring action or state parameter makes it an actionless or stateless reducer respectively. There are reasons to do so, I wrote about that and when that’s useful in Actionless and Stateless Reducers in React. ... memo is for optimizing rendering behavior, it lets you skip re-rendering a component when its props are unchanged 4.
🌐
Reddit
reddit.com › r/typescript › react-typescript complaining about optional props missing (defined with prop-types)
r/typescript on Reddit: React-Typescript complaining about optional props missing (defined with prop-types)
May 5, 2022 -

Hi, I'm converting a React JS codebase to TS.

I just converted a component (`TabButton) that uses an Icon component that is not converted yet but uses prop-types. The problem is that TS (in TabButton) is complaining that Icon misses some props but they should be completely optional as in Icon I didn't require them.

The error text is: Type '{ component: ReactNode; }' is missing the following properties from type '{ [x: string]: any; component: any; color: any; hoverColor: any; className: any; onClick: any; }': color, hoverColor, className, onClick ts(2739)

What can I do? Thanks

TabButton.tsx Hovering over Icon in TabButton.tsx Icon.js
🌐
Better Programming
betterprogramming.pub › 5-recipes-for-setting-default-props-in-react-typescript-b52d8b6a842c
5 Recipes for Setting Default Props in React and TypeScript | by Guillaume Renard | Better Programming
September 28, 2022 - You can learn more about this in the React docs. Similar to the previous example, sometimes you just want to create a component with default props and let the caller override them as needed. Here is a pattern that I like to use in my unit tests. It uses the Partial type of TypeScript to make all properties optional (even the ones that are not marked optional).