In Typescript, custom scalar types are emitted like:
export type Foo = any;
How can I make the emitted Foo refer to my existing types?
For example, if somewhere else in my code base, I have:
class Foo {
bar: string
someMethod() {
...
}
}
I know this supports templating, but even with templating, I'm not sure how to make Foo in the generated types refer to my project's Foo. It seems like I'd need to import existing scalar definitions into my schema template? Or I'd need to define all my custom scalars in templates? Both of these sound pretty unmaintainable. Is there some convenient way to do this? Or is there an example for solving this sort of problem?
PS. Thank you for this package!
@garrettm
I think we can add a custom configuration per each generator, and pass it via gql-gen.json config file. this way we can add custom scalars mapping (and also an import from the file that contains the interface).
What do you think?
Correct me if I'm wrong, here's what I'm imagining, given what you said:
import * as Extern from './extern'
export type ScalarName = Extern.ScalarName
The user can export scalar types from this extern.ts file, and the TS compiler will complain if you forget one.
@garrettm yeah it makes sense.
I'm currently working on the generator-specific configuration, and then we will be able to implement this feature
@dotansimha sounds good. If you're interested in letting someone else do the work, point me in the direction when ready and I can take a look.
I am curious if there is any progress on this? Would love to be able specify types for my scalars :)
@dotansimha facing same issue here. In my case I have a simple scalar Date and I would like to avoid generator to add export type Date = any; in the output since I already have a Date object globally available.
I see, @pleerock . I am thinking about the right solution for this.
We can easily pass custom configuration, so maybe a map like that:
{
config: {
scalars: [
{ scalar: "Date", type: "Date" }
]
}
}
And if you want to use a custom TypeScript type you wrote, for example: MyDateType and map it to a specific GraphQL Scalar, we might need import as well:
{
config: {
scalars: [
{ scalar: "Date", type: "MyDateType", import: "../../types/my-date-type" }
]
}
}
And it will also add the import on top of the file.
What do you think?
It will definitely resolve most of issues.
I like the typescript solution. I actually came across a a use-case with scalars today that it would solve. My other idea was to patch the generated code to add an import and replace the generated type alias with a regex, but this solution is of course much nicer :-).
One note about the import. Lets say you want to do a named import, how would that work? Perhaps something like this could work:
{
config: {
imports: ["import {MyDateType}" from "../datelib", import {MyFooType} from "../foolib" ]
scalars: [
{ scalar: "Date", type: "MyDateType"},
{ scalar: "Foo", type: "MyFooType"}
]
}
}
@jonaskello yeah you are right, your examples supports more use cases (such as named import, default import or any other way).
For query/mutation code generation, I use apollo-cli, which has the flag --customScalarsPrefix when using codegen
// with --customScalarsPrefix=GQL
interface SomeType {
date: GQLDate;
}
GQLDate will not be exported in the generated types, and I keep a separate .d.ts with
declare type GQLDate = Date;
Think this is a nice solution for people who either already have their types globally available, and/or want to avoid name collisions with similarly named types
Note: Not suggesting that
apollo-clican be used instead (it can't), just sharing as inspiration for a potential fix
@dotansimha Since new #444 was released, there seems to be an issue with my JSON scalar type.
schema
scalar JSON
type foo {
bar: JSON!
}
generated types
export type JSON = any; // as before
export interface foo {
bar: Json; // not as before (previously, i would see JSON here)
}
I'm aware of the new scalars option for gql-gen.json but this doesn't help me as it results in the following
export type JSON = MyFancyType; // ok
export interface foo {
bar: Json; // Json != JSON
}
I published a canary version: 0.11.0-alpha.4c054a57
Could you check if it works for you?
Successfully published:
@kamilkisiela with 0.11.0-alpha.4c054a57 of generator & template, I now get
export type Json = any;
export interface foo {
bar: Json;
}
This works but why can't it be JSON in full caps, as found in my schema?
scalar JSON
Is this still waiting for release?
@elie222 You can use ScalarsMap now.
I'm using typescript, typescript-apollo-angular plugins to generate the client
and graphql-iso-date on the server for scalar DateTime.
Does anyone know if adding the following:
config:
scalars:
DateTime: Date
will mean that any field returned from the fetch of DateTime type will be an instance of the JS Date class?
@teebszet yes, but note that you can't really send JS Date over the network, so it will probably get serialized and you'll get it as string in the client, so the server can use JS Date, but the client will get string.
@teebszet yes, but note that you can't really send JS
Dateover the network, so it will probably get serialized and you'll get it asstringin the client, so the server can use JSDate, but the client will getstring.
@dotansimha yeah that makes sense. I guess it would be up to the typescript-apollo-angular plugin to initialise those DateTime fields as Date objects in the client. But I'm not sure if that is a feature that exists or not
@teebszet I think it should be done in Apollo client, during the runtime, and then you can reflect the status of data by using custom scalars in the codegen.
I think you can do that with Apollo Link.
@dotansimha Do you have some useful resources on how it can be done universally with Apollo Link?
I've found this pretty old (but still active) feature request for Apollo client and it almost seems like it's still not possible. It would be really lovely to get ISO date automatically parsed and converted and along with correct typings, it would be a breeze.
This has especially become an issue with date-fns v2 which no longer supports passing a string. Only a Date or number. It's definitely fairly tedious doing that manually whenever there is a need to work with field that contains a stringified date.
@FredyC use parseISO
The previous
parseimplementation was renamed toparseISO.
Can anyone update on this? I am still not able to convert custom scalars. This is my codegen.yml but it doesn't work.
overwrite: true
schema: 'schema.graphql'
generates:
src/generated/graphql.tsx:
config:
scalars:
Long: number
BigDecimal: number
plugins:
- 'typescript'
- 'typescript-operations'
- 'typescript-react-apollo'
- 'typescript-graphql-files-modules'
- 'typescript-document-nodes'
- 'fragment-matcher'
./graphql.schema.json:
plugins:
- 'introspection'
@finaxar-arthur What do you mean by converting custom scalars? If you have any issues, could you please create a new issue with a minimal reproduction?
@finaxar-arthur the config must be at the top, like
overwrite: true
schema: 'schema.graphql'
config:
scalars:
Long: number
BigDecimal: number
Most helpful comment
I see, @pleerock . I am thinking about the right solution for this.
We can easily pass custom configuration, so maybe a map like that:
And if you want to use a custom TypeScript type you wrote, for example:
MyDateTypeand map it to a specific GraphQL Scalar, we might needimportas well:And it will also add the import on top of the file.
What do you think?