Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: Reflect.getMetadata is not a function #21

Closed
4F2E4A2E opened this issue Feb 5, 2018 · 7 comments
Closed

TypeError: Reflect.getMetadata is not a function #21

4F2E4A2E opened this issue Feb 5, 2018 · 7 comments
Labels
Question ❔ Not future request, proposal or bug issue Solved ✔️ The issue has been solved

Comments

@4F2E4A2E
Copy link
Contributor

4F2E4A2E commented Feb 5, 2018

Hi there 👋
I've posted this question on the apollo slack #general and after looking up and testing all projects related to this on github I finally stumble upon this amazing project. I am very hopeful on this one.

Our project have a lot of types definitions written in typescript as interfaces, so reusing them would be a great benefit in terms of time, reusability, type safety ,stability and greatness :)

So thank you for maintaining this 👍
Still, I am having a hard time trying to get a minimal viable example working.

"dependencies": {
  "reflect-metadata": "^0.1.12",
  "type-graphql": "^0.1.2"
}
// example.ts
import {Field, GraphQLObjectType, ID} from 'type-graphql';

@GraphQLObjectType()
class Recipe {
    @Field(type => ID)
    readonly id: string;

    @Field()
    title: string;

    @Field({nullable: true})
    description?: string;

    @Field({nullable: true})
    averageRating?: number;
}
// test.ts
import {buildSchema} from 'type-graphql';
import {Recipe} from './example';

function test() {
    const schema = buildSchema({
        resolvers: [Recipe],
    });
    console.log(schema);
}

test();
ts-node -O '{"module": "commonjs"}' test.ts
[..]\node_modules\type-graphql\helpers\findType.js:7
    const reflectedType = Reflect.getMetadata(metadataKey, prototype.constructor.prototype, propertyKey);
                                  ^
TypeError: Reflect.getMetadata is not a function
    at Object.findType ([..]\node_modules\type-graphql\helpers\findType.js:7:35)
    at Field ([..]\node_modules\type-graphql\decorators\Field.js:14:53)
    at __decorate ([..]\src\main\ts\models\example\example.js:5:110)
    at Object.<anonymous> ([..]\src\main\ts\models\example\example.ts:6:5)
    at Module._compile (module.js:660:30)
    at Object.Module._extensions..js (module.js:671:10)
    at Module.load (module.js:573:32)
    at tryModuleLoad (module.js:513:12)
    at Function.Module._load (module.js:505:3)
    at Module.require (module.js:604:17)

Any help would be much appreciated.

@MichalLytek
Copy link
Owner

Hi @4F2E4A2E!
Thanks, I'm glad to hear that 😊

Reflect.getMetadata is not a function means you haven't imported the reflect-metadata shim. Please take a look at the installation section:
https://github.com/19majkel94/type-graphql#installation

reflect-metadata shim is required:
make sure to import it on top of your entry file (before you use/import type-graphql or your resolvers):

You can see this in the examples on the repo too:
https://github.com/19majkel94/type-graphql/blob/master/examples/01-simple-usage/index.ts#L1

@MichalLytek MichalLytek added the Question ❔ Not future request, proposal or bug issue label Feb 5, 2018
@4F2E4A2E
Copy link
Contributor Author

4F2E4A2E commented Feb 5, 2018

doh! Of course i forgot about the reflect-metadata import, sorry for that. The minimal example worked just fine.
Is there also a way of converting interfaces directly? Like so:

@GraphQLObjectType()
export interface Recipe {
    @Field(type => ID)
    readonly id: string;

    @Field()
    title: string;

    @Field({nullable: true})
    description?: string;

    @Field({nullable: true})
    averageRating?: number;
}

@MichalLytek
Copy link
Owner

No, interfaces are removed at compilation so they doesn't exist at runtime. However you can just use abstract classes as interfaces 😉

@GraphQLObjectType()
export abstract class IRecipe {
    @Field(type => ID)
    readonly id: string;

    @Field()
    title: string;

    @Field({nullable: true})
    description?: string;

    @Field({nullable: true})
    averageRating?: number;
}

class SpecialRecipe implements IRecipe {
  // impl...
}

@4F2E4A2E
Copy link
Contributor Author

4F2E4A2E commented Feb 5, 2018

It's working fine this way. I still will pursue a way to automatise it in order to not be invasive with the already declared interface types.
Does this mean that this issue #6 is obsolete? What is planed to support there?

@MichalLytek
Copy link
Owner

I still will pursue a way to automatise it in order to not be invasive with the already declared interface types.

abstract class is a drop-in replacement for TS interface, you can just do text search&replace and it will work in your codebase 😉

@4F2E4A2E
Copy link
Contributor Author

4F2E4A2E commented Feb 5, 2018

abstract class is a drop-in replacement for TS interface, you can just do text search&replace and it will work in your codebase

Thank you for that info, i will do exactly that!
But again, why not to do this in here and replace it seamless? This way interfaces would work as well without anyone having to change their typings, right? This way more people and implementations could be reached. Sometimes you cant't change the entity definition.

@MichalLytek
Copy link
Owner

Because interfaces doesn't exist in JS (runtime) so they are removed on TypeScript compilation step. So when the app starts, I'm not able to figure out what is the type, what fields does it have, etc. so there's no way to generate the schema with GQL types from interfaces.

The only way is to use classes and decorators to collect metadata emitted by TypeScript compiler, just the way TypeORM or class-validiator works. Or create an "offline" code generator that will read the source and comments, just like ts2gql works, but it's not the goal of TypeGraphQL.

I am closing this issue as the main problem is solved. If you want to know more details about types reflection we can discuss on gitter 😉
https://gitter.im/type-graphql/Lobby

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Question ❔ Not future request, proposal or bug issue Solved ✔️ The issue has been solved
Projects
None yet
Development

No branches or pull requests

2 participants