Reputation: 2159
I am trying to create a react reusable component: a table that should either be a list of Teams or a list of Games. Hence the GraphQL query is different based on what is fetched.
so I have those interfaces and types:
export interface Team {
id: string;
name: string;
}
export interface Game {
id: string;
competition: string;
}
export interface Data {
allElems?: Team[] | Game[]
[elements: string]: Team[] | Game[] | undefined
}
My component is like so :
interface SectionTableProps {
query: object
}
class SectionTableQuery extends Query<Data, {}> {}
class SectionTable extends React.Component<SectionTableProps, {}> {
constructor(props: SectionTableProps) {
super(props);
}
render() {
return (
<SectionTableQuery query={this.props.query}>
{({ data = {}, error, loading }) => {
if (loading) {
return <tbody><tr><td>LOADING</td></tr></tbody>
};
if (error !== undefined) {
return <tbody><tr><td>ERROR</td></tr></tbody>
};
return (
<tbody>
{Object.keys(data).map(elements => {
data[elements].map(
elem => (
<tr key={elem.id} >
<th scope="row">{elem.id}</th>
{Object.keys(elem).map(k => {
if (k !== "id" && k !== "__typename") {
return <td key={elem[k]}>{elem[k]}</td>
}
})}
</tr>
)
)
}
)
}
</tbody>
);
}}
</SectionTableQuery>
)
}
}
but I get the following error :
TypeScript error: Cannot invoke an expression whose type lacks a call signature. Type '(<U>(callbackfn: (value: Team, index: number, array: Team[]) => U, thisArg?: any) => U[]) | (<U>(callbackfn: (value: Game, index: number, array: Game[]) => U, thisArg?: any) => U[])' has no compatible call signatures. TS2349
42 | <tbody>
43 | {Object.keys(data).map(elements => {
> 44 | (data[elements] || []).map(
| ^
45 | elem => (
46 | <tr key={elem.id}>
47 | <th scope="row">{elem.id}</th>
why is that so ? I really don't know why Game
and Team
aren't compatible...
Upvotes: 0
Views: 1819
Reputation: 2159
Just found a solution; don't know if it's the best though :
In my case I have to use declaration merging :
I can't write
export interface Team {
id: string;
name: string;
}
export interface Game {
id: string;
competition: string;
}
export interface Data {
allElems?: Team[] | Game[]
[elements: string]: Team[] | Game[] | undefined
}
as I'll get the error mentionned in my initial post. Instead, I have to declare my interfaces like so:
//team
interface Elem {
id: string;
name?: string;
[attr: string]: string | number | undefined
}
//game
interface Elem {
id: string;
homeTeamScore?: number
competition?: string
round?: string
}
export interface Data {
elem?: Elem
[elements: string]: Elem | undefined
}
At the most basic level, the merge mechanically joins the members of both declarations into a single interface with the same name.
Upvotes: 1