7

How does one define the contextTypes in TypeScript?

I have a component (note: I'm unsure of the necessary type of router as detailed in this question but that should be irrelevant here)

export class Repos extends React.Component<ReposProps, {}> {
    context: {
        router: History
    }

    static contextTypes = {
        router: React.PropTypes.object
    };

It has a function

    public handleSubmit(event: React.FormEvent) {

at the end of that function, it calls on context

        this.context.router.push(path);
    }

The component has a form

    public render() {
        return (
            {/* ... */}
                <form onSubmit={this.handleSubmit}>
        );
    }
}

However, on the line with this.context.router.push(path); I receive the error "Uncaught TypeError: Cannot read property 'router' of undefined" When compiling this same code, I received the TypeScript error in the file that uses Repos in a Router:

ERROR in ./index.tsx
(14,34): error TS2322: Type 'typeof Repos' is not assignable to type 'string | ComponentClass<any> | StatelessComponent<
any>'.
  Type 'typeof Repos' is not assignable to type 'StatelessComponent<any>'.
    Types of property 'contextTypes' are incompatible.
      Type '{ router: Requireable<any>; }' is not assignable to type 'ValidationMap<any>'.

Changing the contextTypes to

static contextTypes: React.ValidationMap<any> = {
    router: React.PropTypes.object
};

fixed the TypeScript error, although I doubt it was necessary; I suspect a different problem that is the cause of both of these issues.

According to discussions in TypeScript issue 4785: How to use React contextTypes in Typescript 1.6?, the code above is correct. If it helps, I'm using TypeScript 1.7.3, React 0.14.7 and react-router 2.0.0.

4
  • If you share the code I can have a look. I personally haven't used context or router as of yet :) Commented Feb 23, 2016 at 3:19
  • Link to specific commit where things are broken -- This compiles with TypeScript 1.7.3, but I just noticed 1.8.2 broke it. Run w/ npm start, navigate to localhost:8080/repos, type in the two text fields and press Go to see the Router undefined error happen. Commented Feb 23, 2016 at 14:20
  • I updated that repo with a temp fix for the TS 1.8.2 compile issue. Commented Feb 23, 2016 at 15:26
  • 1
    Wow I'm an idiot. The problem is binding this. I don't know if its appropriate to keep this question open or to delete it now. Commented Feb 23, 2016 at 19:01

1 Answer 1

3

We've all seen this problem at one time or another in our careers. It's surprising that I didn't catch this.

The problem is that the context of this in handleSubmit() is different because of how handleSubmit is called. Changing handleSubmit into a fat arrow definition works:

public handleSubmit = (event: React.FormEvent) => {

In this particular case, I overlooked that because I don't run into this problem often in the TypeScript world (I also don't work with DOM elements often, and have been with React for under a week... no excuses, I know)

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

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.