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.

Answer from Aaron Beall on Stack Overflow
🌐
React TypeScript Cheatsheets
react-typescript-cheatsheet.netlify.app › typing defaultprops
Typing defaultProps | React TypeScript Cheatsheets
For TypeScript 2.9 and earlier, there's more than one way to do it, but this is the best advice we've yet seen: type Props = Required<typeof MyComponent.defaultProps> & { /* additional props here */ }; export class MyComponent extends React.Component<Props> { static defaultProps = { foo: "foo", }; } Our former recommendation used the Partial type feature in TypeScript, which means that the current interface will fulfill a partial version on the wrapped interface.
🌐
DEV Community
dev.to › bytebodger › default-props-in-react-typescript-2o5o
Default Props in React/TypeScript - DEV Community
July 29, 2020 - One thing I don't like about this approach is that I couldn't seem to get it to work unless I also defined default values inside defaultProps for the required props. If I remove requiredString and requiredNumber from the defaultProps definition, TS complains about it. Still - that's not really that big of a deal. So is this the end of the article? The "real" solution for default props in React/TS?
Discussions

reactjs - How to define defaultProps in React 18 TypeScript without optionals - Stack Overflow
It's true you're not forced to write importantProp = 'not undefined', but if you forget then typescript knows it's string | undefined, and will give an error if you use it as a string on later lines. ... Defining some sort of defaultProps object also makes is possible to share the same defaults ... More on stackoverflow.com
🌐 stackoverflow.com
Default props not working in functional component
TypeScript Version: 3.4.5 Search Terms: react default props defaultProps functional component stateless Code import React from "react"; interface Props { name: string; optional: string; } const Com... More on github.com
🌐 github.com
20
May 4, 2019
How to specify (optional) default props with TypeScript for stateless, functional React components?
I'm trying to create a stateless React component with optional props and defaultProps in Typescript (for a React Native project). This is trivial with vanilla JS, but I'm stumped as to how to achie... More on stackoverflow.com
🌐 stackoverflow.com
TypeScript + React: defining defaultProps correctly
You can check my react samples fork on github.com/boxstart/react-typescript-samples. Example 02 contains the optional property and defaultProps from my example above. More on stackoverflow.com
🌐 stackoverflow.com
May 5, 2017
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
};
🌐
Medium
medium.com › @martin_hotell › react-typescript-and-defaultprops-dilemma-ca7f81c661c7
React, TypeScript and defaultProps dilemma | by Martin Hochel | Medium
August 20, 2018 - Well TypeScript 2.8 introduced a very powerful feature — conditional types. Let’s use the new and shinny feature with more functional approach, shall we ? We can define a factory function/high order function, for declaring defaultProps and leveraging conditional types to correctly resolve our props API. ... withDefaultProps high order function used for Component implementation with defaultProps and type flow · I like this ! We don’t use React API for defining defaultProps explicitly, this is handled by our withDefaultProps function.
🌐
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 - Similar to the previous example, ... 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)....
🌐
Medium
chrisfrewin.medium.com › react-with-typescript-optional-props-with-default-values-cf4c8370659f
React with TypeScript: Optional Props with Default Values | by Chris Frewin | Medium
October 10, 2021 - We can then use the TypeScript ... values by only taking the IMyComponentOptionalProps: const defaultProps: IMyComponentOptionalProps = { color: "red", fontSize: 40, };...
Find elsewhere
🌐
Matt Ferderer
mattferderer.com › default-props-in-react-with-typescript
How to use Default Props in React with TypeScript | Matt Ferderer
September 20, 2018 - import * as React from "react" type CardColors = "red" | "blue" export interface ColorCardProps { color: CardColors // Don't use the optional parameter below // color?: CardColors } export interface ColorCardState { color: CardColors } export default class ColorCard extends React.Component<ColorCardProps, ColorCardState> { static defaultProps = { color: "red" } state = { color: this.props.color } flipColor = () => { this.setState((prevState, props) => { return { color: prevState.color === "red" ?
🌐
GitHub
github.com › microsoft › TypeScript › issues › 31247
Default props not working in functional component · Issue #31247 · microsoft/TypeScript
May 4, 2019 - import React from "react"; interface Props { name: string; optional: string; } const Component = ({ name, optional = "default" }: Props) => ( <p>{name + " " + optional}</p> ); const Test = () => <Component name="test" />; Expected behavior: According to the TypeScript 3.0 release notes, the optional prop should not be required in Test as it has been defined with a default using the ES2015 default initializers feature in Component.
Author   AzureMarker
🌐
React
legacy.reactjs.org › docs › typechecking-with-proptypes.html
Typechecking With PropTypes – React
class Greeting extends React.Component { render() { return ( <h1>Hello, {this.props.name}</h1> ); } } // Specifies the default values for props: Greeting.defaultProps = { name: 'Stranger' }; // Renders "Hello, Stranger": const root = ...
🌐
GitHub
github.com › typescript-cheatsheets › react
GitHub - typescript-cheatsheets/react: Cheatsheets for experienced React developers getting started with TypeScript · GitHub
Our former recommendation used the Partial type feature in TypeScript, which means that the current interface will fulfill a partial version on the wrapped interface. In that way we can extend defaultProps without any changes in the types! interface IMyComponentProps { firstProp?: string; secondProp: IPerson[]; } export class MyComponent extends React.Component<IMyComponentProps> { public static defaultProps: Partial<IMyComponentProps> = { firstProp: "default", }; }
Starred by 47K users
Forked by 4.3K users
Languages   JavaScript 93.9% | CSS 5.8% | Shell 0.3%
🌐
Medium
medium.com › @swarnavo.pramanik1701 › prop-types-and-default-props-in-react-7731a43066bf
Prop Types and Default Props in React | by Swarnavo Pramanik | Medium
January 3, 2024 - prop-types is a library with which you can check the type of props in React. With defaultProps, we can pass default values to props. TypeScript is used to handle type checks and default values in large projects.
🌐
Fettblog
fettblog.eu › typescript-react › prop-types
TypeScript and React: Prop Types
We were talking about defaultProps in the components chapter. You can combine defaultProps and propTypes. E.g. when you set a prop type to isRequired, but add a defaultProp for it, TypeScript understands that this becomes optional.
🌐
TypeScript
typescriptlang.org › docs › handbook › release-notes › typescript-3-0.html
TypeScript: Documentation - TypeScript 3.0
Use static defaultProps: Pick<Props, "name">; as an explicit type annotation instead, or do not add a type annotation as done in the example above. For function components (formerly known as SFCs) use ES2015 default initializers: ... Corresponding changes to add LibraryManagedAttributes definition ...
🌐
LogRocket
blog.logrocket.com › home › a complete guide to react default props
A complete guide to React default props - LogRocket Blog
June 4, 2024 - With the addition of static class ... { // ...implement render method } // Set default props static defaultProps = { theme: "secondary", label: "Button Text" } }...
🌐
Webdevtutor
webdevtutor.net › blog › typescript-defaultprops
Understanding TypeScript DefaultProps in React
Here's an example of how you can define default props in a TypeScript React component: interface MyComponentProps { text: string; count: number; } const MyComponent: React.FC<MyComponentProps> = ({ text, count }) => { return ( <div> <p>{text}</p> <p>{count}</p> </div> ); }; MyComponent.defaultProps = { text: "Default Text", count: 0, };
🌐
GitHub
github.com › DefinitelyTyped › DefinitelyTyped › issues › 28515
[@types/react] Type-checking for defaultProps · Issue #28515 · DefinitelyTyped/DefinitelyTyped
August 29, 2018 - import React from 'react'; type Props = { foo: string }; class Foo extends React.Component<Props> { static defaultProps = { foo: 123, }; render() { return <div />; } }
Author   brieb
🌐
DEV Community
dev.to › prithpalsooriya › how-to-type-react-defaultprops-ji6
How to Type React DefaultProps - DEV Community
July 22, 2021 - But TypeScript should have picked this up when we used it as a prop for our List component, so why did we not get any errors about this? The type ListProps for our component is NOT the true & final prop types when we are instantiating the new JSX List element. It merges the props we provide it at the start (the extends React.Component<ListProps>) with the typeof defaultProps.