1

I have an array which is state entry that I populate in componentDidMount lifecycle hook, and it is quite simple:

state{
      array:[{a:0,b:0},{a:1,b:1},{a:2,b:2}]
     }

When I try to access it, however I am always getting an error:

Property 'a' does not exist on type 'never'.

I think I am having troubles with declaring an interface here, can't find a proper way to do that. Something like this would probably do:

interface IState{
     array: object[]
}

Full version of component :

import * as React from "react";
import phrasalVerbs from "../data/phrasalVerbs";

interface IAnswerOptions {
   pVerb: string;
   meaning: string;
 }

interface IState {
  pVerbs: object;
  progress: number;
  answerOptions: IAnswerOptions[];
}

class PhrasalVerbs extends React.Component<{}, IState> {
  public state = {
    pVerbs: phrasalVerbs,
    progress: 0,
    answerOptions: []
  };

  public componentDidMount() {
    this.randomVariants();
  }

  public randomVariants = () => {
    let randomVariants: any[] = [];
    const currentVerbs = this.state.pVerbs.data;
    const shuffledVerbs = currentVerbs
      .map(a => [Math.random(), a])
      .sort((a: any, b: any): any => a[0] - b[0])
      .map(a => a[1]);
    randomVariants = [shuffledVerbs[0], shuffledVerbs[1], shuffledVerbs[2]];
    this.setState({
      ...this.state,
      answerOptions: randomVariants
    });
  };

  public render() {
    const { pVerbs, progress } = this.state;

    return (
      <div>
        <div>{pVerbs.data[progress].pVerb}</div>
        {/* <div>
          {this.state.answerOptions
            ? this.state.answerOptions[0].meaning
            : null}
        </div> */}
      </div>
    );
  }
}

export default PhrasalVerbs;
2
  • Your objects aren't really valid. Two properties named c? Commented Oct 4, 2018 at 20:47
  • My bad, did that by mistake Commented Oct 4, 2018 at 20:48

2 Answers 2

9

You can define a type for your object:

interface IMyObject {
    a: number;
    b: number;
}

interface IState {
    array: IMyObject[];
}

class MyComponent extends React.Component<any, IState> {
    state = {
        array:[{a:0,b:0},{a:1,b:1},{a:2,b:2}]
    };

    render() {
        // should be OK
        const firstA: number = this.state.array[0].a;

        return <h1>{firstA}</h1>;
    }
}

Edit: looking into your code, it appears you’ve accidentally overridden the type of state. Typescript will automatically (and sometimes unhelpfully) allow you to override the types of fields in classes, so although you have your Component defined in terms of IState, the internal state property’s type is defined by the default value you gave it.

In this situation, an empty array has an inferred type of never[], so you end up with an array whose elements you can’t use.

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

7 Comments

Still does not work, for some reason. If I do it by declaring state in the state object it is working fine, but using componentDidMount breaks everything
Even if I use :any when declaring a type for my array in interface it's not working
Please post the full version of your React component within your original post.
Done, if you need something else, feel free to ask! The commented code is the one that produces error.
Try going public state: IState = { ... }, you might be falling victim to type overriding.
|
1

Hmm did you setup strictPropertyInitialization in tsconfig?

1 Comment

Nope, and this problem is driving me crazy already. Maybe there is at least some workaround?

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.