0

I am fairly new to TypeScript, and have been handed an ES6 based react project, and would like to Migrate over to TypeScript for a more integrated state. Anything following a (this.) seems to break with error (Property "foo" does not exist on Type "bar")

import * as React from 'react';
import { Component } from 'react';
class Clock extends Component {
    constructor(props: {}) {
        super(props);
        this.state = {
            date: new Date()
        };
    }

    componentDidMount() {
        this.timerId = setInterval(
            () => this.tick(), 500
        );
    }

    componentWillUnmount() {
        clearInterval(this.timerId);
    }

    tick() {
        this.setState({
            date: new Date()
        });
    }

    render() {
        const options = { hour24: false };

        return (
            <div className="clockDesign">{this.state.date.toLocaleString('en-US', options)}</div>
        );
    }
}

export default Clock;

My question is this. How would I go about converting the inline definitions to types within my class statement?

3 Answers 3

1

Use interfaces (https://www.typescriptlang.org/docs/handbook/interfaces.html):

interface Props = {

};

interface State = {
  date: Date;
}

class Clock extends Component<Props, State> {
  private timerId: any;

  constructor(props: Props) {
    super(props);

    this.state = {
      date: new Date()
    };
  }
  ...
}
Sign up to request clarification or add additional context in comments.

Comments

0

Declare the fields of your class before assigning them. For example:

class Clock extends Component {

    private state: { date: Date }

    constructor(props: {}) {
        super(props);
        this.state = {
            date: new Date()
        };
    }

    // ...
}

Or if state is supposed to be inherited from Component, then you might have some problems with your typings (npm install @typings/react).

4 Comments

Would this also apply to the (this.timerId) statements? I should have been more clear in my question, but the date was a secondary issue as well
Yes, there you would use private timerId: number (or public depending on your case)
Thank you very much, testing now. I am on hold for accepting.
That seemed to do the trick. I had to switch them all to public, to prevent an incorrect extension error.
0

You need to add correct generic arguments and you need to define the class properties. See comments.

import * as React from 'react';

interface IProps { }
interface IState {
    date: Date;
}

class Clock extends React.Component<IProps, IState> { //You need to define both props and state
    constructor(props: {}) {
        super(props);
        this.state = {
            date: new Date()
        };
    }

    timerId: any; //Props needs to be defined;
    componentDidMount() {
        this.timerId = setInterval(
            () => this.tick(), 500
        );
    }

    componentWillUnmount() {
        clearInterval(this.timerId);
    }

    tick() {
        this.setState({
            date: new Date()
        });
    }

    render() {
        const options = { hour24: false };

        return (
            <div className="clockDesign"> {this.state.date.toLocaleString('en-US', options)} </div>
        );
    }
}

export default Clock;

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.