31

I had a class component with another class component as his static property. Now I switched to a function component and I don't know how to keep the static property.

class Panel extends React.Component<Props> {
  public static Fieldset = PanelFieldset;
}

class PanelFieldset extends React.Component<Props> {
  ...
}

class App extends React.Component<Props> {
  public render() {
    return (
      <Panel>
        <Panel.Fieldset>
          ...
        </Panel.Fieldset>
      </Panel>
    )
  }
}

Now, switching to function component:

const Panel: React.FunctionComponent<Props> = (props) => {
  Panel.Fieldset = PanelFieldset;
}

but I get the error: Property 'Fieldset' does not exist on type 'FunctionComponent'.ts(2339)

Any help?

1

4 Answers 4

36

With implicit typing (Best Solution)

The following shows an approach where you don't have to type your static properties explicitly. I personally prefer this over any other solution, since it is the shortest and most clean way.

const PanelComponent: React.FC<Props> = (props) => {
 ...
}

export const Panel = Object.assign(PanelComponent, { PanelFieldset })

With explicit typing (Previous Solution)

If you want to type your static properties explicitly, extending @Andrew's answer, using typeof PanelFieldset should be more convenient to type your component.

type IPanel<P> = React.FunctionComponent<P> & {
  Fieldset: typeof PanelFieldset; // add this
}

const Panel: IPanel<Props> = (props) => {
}

Panel.Fieldset = PanelFieldset;

Source: https://github.com/react-bootstrap/react-bootstrap/blob/master/src/Dropdown.tsx#L230-L237

Sign up to request clarification or add additional context in comments.

Comments

21

For static properties on a function you declare them on the function itself i.e.

function Panel() {
}
// static props
Panel.Fieldset = PanelFieldset

A similar approach can be seen for setting propTypes on a component. I assume in TS that would look like:

Panel.Fieldset: React.Component<Props> = PanelFieldset

6 Comments

@JohnnyZabala I misread, I thought they had Panel.Fieldset: PanelFieldset, d'oh
Oh I see! Yeah, you are right in that case, it wouldn't be valid js.
Thank you but I'm getting the same error: Property 'Add' does not exist on type FunctionComponent
@SimoneConti that doesn't seem related? There is on Add property in the example given.
It is related. React.Component<Props> can only define keys inside props. Fieldset is a propery on the function itself, not inside props
|
10

React.FunctionComponent is scoped purely within the key props, which you discovered does not work when you want to add a property that is not in the props key. In order to properly type it, you need to make your own type and extend it.

After that, assign it outside of the function

type IPanel<P> = React.FunctionComponent<P> & {
  Fieldset: any //whatever type it actually is
}

const Panel: IPanel<Props> = (props) => {
}

Panel.Fieldset = PanelFieldset;

2 Comments

Thank you, I ended up with: const Panel: React.FunctionComponent<Props> & { PanelFieldset: React.FunctionComponent<PanelFieldsetProps> }
Quite a bit to put as an inline type, but I'm not going to tell you how to write your code ;). Glad it worked out, and good luck with the rest of your project
5

Typescript compiler is telling you that you are using a property that is not defined in the function. Move Panel.Fieldset = PanelFieldset; outside de function.

// Bad
function A() {
  A.B = 'hello'
}

// Good
function A() {}
A.B = "Here we go."

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.