0

I am new to js/ts but experienced in C#. Now I'm learning React and want to use typescript. I try to add types to this demo project: https://github.com/bradtraversy/projectmanager/tree/master/src .

Code so far:

export interface IProjectItem {
  title: string;
  category: string;
}

export interface IProjects {  
  projects : {
    [index: number]: IProjectItem;  
  };
}


class App extends React.Component<object,IProjects> {

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

  this.state = {
    projects: [
    {
      title: 'Business Website',
      category: 'Web Design'
    },
    ....
  }

  render() {
    return (      
      <div className="App">
        MyApp
        <Projects projects={ this.state.projects }/>
      </div>
    );
  }
}

class Projects extends React.Component<IProjects,object> {    

  render() {    

    if (this.props.projects)
    {
      this.props.projects.map( project => { //ERROR Property map not found for type [index:number]
        console.log(project);
      });
    }
    console.log(this.props);

    return (      
      <div className="projects">
        All Projects
      </div>
    );
  }
}

Obviously the .map() function is not found. I think I have to change the used interfaces/types, but what is the right one?

Tobias
  • 15
  • 1
  • 2
  • 6

2 Answers2

3

As you suspected, the issue is with your type definitions - in particular, this one:

export interface IProjects {  
  projects : {
    [index: number]: IProjectItem;  
  };
}

What this is saying is, 'an object that implements IProjects will contain projects, which is an object that can be indexed with numbers'. Note that an object that can be indexed with numbers is not the same thing as an array, and will not have any of the array prototype methods like map!

This, on the other hand, will define it as an array:

export interface IProjects {  
  projects: IProjectItem[];
}
Joe Clay
  • 33,401
  • 4
  • 85
  • 85
  • Thank you for the detailed answer.! What I thought is, that [index: number]: IProjectItem; would result in something similar to c#'s "IDictionary" which implements IDictionary down the down the inheritance hierarchy - Beginner's mistake. – Tobias Dec 01 '17 at 12:59
  • @Tobias: If you did want to create a dictionary of numbers to objects, ` `[index: number]: IProjectItem` *is* probably how you'd want to do it - however, you can't `map` over objects in JS without a little bit of boilerplate - see this question/answer: https://stackoverflow.com/questions/14810506/map-function-for-objects-instead-of-arrays – Joe Clay Dec 01 '17 at 13:02
2

You are using this.props.projects.map;

map is for array [].

But your variable projects is a JSON Object;

projects : {
    [index: number]: IProjectItem;  
  };

Change its type. Maybe

project: any[]// you will have a generic array object

Or

project: IProjectItem[] // you will have an array containing items of "IProjectItem"
edkeveked
  • 17,989
  • 10
  • 55
  • 93