typescript error: ' ' only refers to a type, but is being used as a namespace here

Viewed 4533

I went through several similar questions but wasn't able to get anywhere in solving this. I was following along with a tutorial from 2019 and I'm having trouble figuring out the right way to do the same thing in 2020. Here's the line I'm getting an error on:

ERROR: 'HotelsQuery' only refers to a type, but is being used as a namespace here.ts(2702)

type IHotelsProps = HotelsQuery.Props<IHotelsBaseProps> & RouteComponentProps;

I'm passing HotelsQuery from my generatedModels file, defined as:

export type HotelsQuery = (
  { __typename?: 'Query' }
  & { hotels?: Maybe<(
    { __typename?: 'HotelTypeConnection' }
    & { edges: Array<Maybe<(
      { __typename?: 'HotelTypeEdge' }
      & { node?: Maybe<(
        { __typename?: 'HotelType' }
        & Pick<HotelType, 'id' | 'title' | 'body'>
      )> }
    )>> }
  )> }
);

And the class it's being passed to:

class Hotels extends React.Component<IHotelsProps, IHotelsState> {
    constructor(props: IHotelsProps) {
        super(props);
        const query = queryString.parse(props.location.search);
        this.state = {
            searchQuery: query && query.search
            ? query.search.toString() : undefined
        };
    }

    public render() {
        const { searchQuery } = this.state;
        const { data } = this.props;

        return (
            <Row>
                <Col span={12} offset={6}>
                    <Divider>Add Hotel</Divider>
                    <Divider>Hotels</Divider>
                    <Input.Search
                        placeholder="Search..."
                        enterButton="Search"
                        defaultValue={searchQuery}
                        onChange={this.handleSearchQueryChange}
                        onSearch={this.handleSearch}
                    />
                    {data!.loading ? (
                        <Spin style={{ marginTop: 16, display: 'block' }} /> )
                        : (
                            <div>
                                {data!.notes!.edges.map(edge => (
                                <Card
                                    key={edge!.node!.id}
                                    style={{ marginTop: 16 }}
                                    actions={[
                                        <Icon
                                            type="delete"
                                            key={edge!.node!.id}
                                            onClick={() => this.handleDeleteHotel(edge!.node!.id)}
                                        />
                                    ]}
                                >
                                    <Card.Meta
                                        title={edge!.node!.title}
                                        description={edge!.node!.body}
                                    />
                                </Card>
                            ))}
                            </div>
                        )}
                </Col>
            </Row>
        );
    }
1 Answers

So I took a stab at the tutorial and wanted to explain how a few parts are working.

First off I only did the front end part so when it came time to running yarn gql-gen I hit a block since the codegen.yml references the backend server for getting the types (I assume?)

overwrite: true
schema: "<http://localhost:8000/graphql/>"
documents: "src/**/*.ts"
generates:
    ./src/generatedModels.tsx:
        config: {}
        plugins:
            - "typescript-common"
            - "typescript-client"
            - "typescript-react-apollo"

Here schema is referring to localhost, so I think you need to have the backend configured correctly to expose the types at /graphql/ directory. I just got an error saying I had no sources so either that didn't happen for you because you had the backend setup or you found another work around that might have been incorrect.

user@computer simplenote % yarn gql-gen --config codegen.yml
yarn run v1.22.5
$ /.../simplenote/node_modules/.bin/gql-gen --config codegen.yml
/.../simplenote/node_modules/graphql/jsutils/devAssert.js:12
    throw new Error(message);
    ^

Error: Must provide Source. Received: undefined.

I do want to point out that the path node_modules/.bin/gql-gen indicates what it is actually using, that is a link to node_modules/graphql-code-generator/__/cli.js so the library you are actually using with the yarn gpl-gen is graphql code generator so the documentation on their site may be of help.

So some options for a way forward I would recommend:

  1. look at the config options in the graphql TypeScript React Apollo docs, there may be default options that have changed since the tutorial was written, in particular hooks are replacing HOCs a lot so it's possible the defaults being different is because of that.
  2. re-check that the backend part is running when you run yarn gql-gen and that if you go to http://localhost:8000/graphql/ in your browser I'd expect some kind of data dump, otherwise the codegen.yml may be unable to get the info it needs to generate relevant type definitions.
  3. abandon using HOCs and move to using hooks, the rest of the tutorial will still probably work you just have a function component instead of a class and use probably useHotels from the code generated. I do highly recommend using hooks, there is a good reason they so rapidly replaced HOCs.

I hope one or both of these leads you in enough of a right direction to figure out how to proceed, happy hunting :)

Related