-
Notifications
You must be signed in to change notification settings - Fork 4
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
Enums break .d.ts typings #179
Comments
I've run into this as well. I've considered going back to the unioned strings, but I'm still unsure. i've also thought about removing the namespace option altogether. in the meantime, the solution i've used is to provide overrides for the formatters. const {
DEFAULT_INTERFACE_BUILDER,
DEFAULT_TYPE_BUILDER,
DEFAULT_ENUM_TYPE_BUILDER,
DEFAULT_EXPORT_FUNCTION
} = require('@gql2ts/language-typescript');
const addConst = input => `const ${input}`;
const overrides = {
generateNamespace: (_, interfaces) => `// tslint:disable
// graphql typescript definitions
${interfaces}
// tslint:enable
`,
interfaceBuilder: (name, body) => DEFAULT_EXPORT_FUNCTION(DEFAULT_INTERFACE_BUILDER(name, body)),
typeBuilder: (name, body) => DEFAULT_EXPORT_FUNCTION(DEFAULT_TYPE_BUILDER(name, body)),
enumTypeBuilder: (name, values) => DEFAULT_EXPORT_FUNCTION(addConst(DEFAULT_ENUM_TYPE_BUILDER(name, values))),
}; this is obviously not great, but will hopefully help in the meantime. I think this is something that should be looked into in v2 #163 |
I can confirm the import {extend} from 'lodash';
import {generateNamespace, ISchemaToInterfaceOptions} from '@gql2ts/from-schema';
import * as fs from 'fs';
import {ITypeMap, IFromQueryOptions} from '@gql2ts/types';
import {DEFAULT_TYPE_MAP, DEFAULT_EXPORT_FUNCTION} from '@gql2ts/language-typescript';
fs.readFile('./src/api/graphql/schema.graphql', {encoding: 'utf8'}, (err, schema) => {
if (err) {
throw err;
}
const options: Partial<ISchemaToInterfaceOptions> = {
typeMap: extend(DEFAULT_TYPE_MAP, {
Date: 'Date',
UUID: 'string'
}) as ITypeMap
};
// @todo: This override is required for a erroneous enum:
// https://github.com/avantcredit/gql2ts/issues/179
const overrides: Partial<IFromQueryOptions> = {
enumTypeBuilder: (name, values) =>
DEFAULT_EXPORT_FUNCTION(`const enum ${name} ${values}`).replace(';', '')
};
const typescriptDefinitions = generateNamespace('GQL', schema, options, overrides);
fs.writeFile('./src/api/graphql/schema.d.ts', typescriptDefinitions, () => {});
}); Note that I'm also replacing the |
@harm-less what's the issue with semicolons? is that just a preference or is something breaking? |
@brettjurgens it is not valid typescript. It creates an error. Edit: : An implementation cannot be declared in ambient contexts. |
@brettjurgens if you want i can put in a PR for this, but maybe not until next week. |
@raysuelzer that'd be great! I'm still unsure if we should even be doing native enums, because they seem to be causing a few problems. We've reverted to using string unions instead |
I think native enums are better for IntelliSense (discovering the members). |
@felixfbecker intellisense works well with string unions as well. Const enums are great, but like you said don't work in certain situations. I think we can keep enums in the from-schema package and use string unions in the from-query. The issue I've been encountering is that two equivalent enums are not equal as far as the type system is concerned. This is mostly an issue with input values (i.e. args or mutations) Typing this on my phone, so hopefully it's coherent 😂 |
Not when the type for the position you are assigning it to cannot be inferred, e.g. cause you are assigning to a variable/property without a type declaration, to a function that takes
That's a problem indeed, and surprises me... |
Ah, you're absolutely correct - good point. I think there's some middle ground that we can hit here, but I'm not entirely sure. I've also thought about using string unions for the values of the fields, but also generating the enum. interface IProduct {
productType: 'typeA' | 'typeB' | 'typeC';
}
const enum ProductType {
typeA = 'typeA',
typeB = 'typeB',
typeC = 'typeC' but I can't decide if I like it or not |
Why not have it configurable? |
@felixfbecker it should be, just trying to figure out what the most sane default behavior is. I don't want people generating code that doesn't work in their usecase by default |
I already convertee everything to enums, but did find string literals to be less of an issue. |
this should be fixed in |
Are you guys generating the typings into a non- |
Yes, I am compiling to a |
@voxmatt , the issue I had even happened when using .d.ts file. It did not happen until after I compiled my angular application in production mode.... Might be an issue with their tree shaking, but it definitely caused errors both ways on my end. |
@felixfbecker did you find a solution for namespace vs. module? |
I am using gql2ts programmatically in a Gulpfile to be able to customize it. This is the task: export async function graphQLTypes(): Promise<void> {
const schemaStr = await readFile(GRAPHQL_SCHEMA_PATH, 'utf8')
const schema = buildSchema(schemaStr)
const result = (await graphql(schema, introspectionQuery)) as { data: IntrospectionQuery }
const formatOptions = (await resolveConfig(__dirname, { config: __dirname + '/../prettier.config.js' }))!
const typings =
'export type ID = string\n\n' +
generateNamespace(
'',
result,
{
typeMap: {
...DEFAULT_TYPE_MAP,
ID: 'ID',
},
},
{
generateNamespace: (name: string, interfaces: string) => interfaces,
interfaceBuilder: (name: string, body: string) =>
'export ' + DEFAULT_OPTIONS.interfaceBuilder(name, body),
enumTypeBuilder: (name: string, values: string) =>
'export ' + DEFAULT_OPTIONS.enumTypeBuilder(name, values),
typeBuilder: (name: string, body: string) => 'export ' + DEFAULT_OPTIONS.typeBuilder(name, body),
wrapList: (type: string) => `${type}[]`,
postProcessor: (code: string) => format(code, { ...formatOptions, parser: 'typescript' }),
}
)
await writeFile(__dirname + '/src/backend/graphqlschema.ts', typings)
} Works really well! Thanks for all the options @brettjurgens |
@brettjurgens I think this would be really useful; enums have a lot of known issues which are unlikely to change anytime soon: microsoft/TypeScript#33283 For example, two different queries might both have a key that's exactly the same shape. All the other keys will be inferred (correctly) as being equivalent, except for the enums. If we could generate string unions instead of enums (or atleast make that a configurable option) that would be amazing. |
Unfortunately the use of real enums means the typings cannot be generated anymore referencing the enums will fail at runtime with
Uncaught ReferenceError: GQL is not defined
. I think usingconst enum
s might work, but I think the better solution here is to generate a proper .ts module. That however gets hairy to combine with external modules, as the current file doesn't export anything and it can't be imported.I would propose to add a new flag
--module
that makes gql2ts output an external module (exporting the types) instead of adeclare namespace
.The text was updated successfully, but these errors were encountered: