Apollo-server: Playground config requires all properties in TypeScript

Created on 24 Sep 2018  Â·  12Comments  Â·  Source: apollographql/apollo-server

ApolloServer constructor accepts parameter playground?: PlaygroundConfig where

export type PlaygroundConfig =
  | RecursivePartial<PlaygroundRenderPageOptions>
  | boolean;

where

type RecursivePartial<T> = {
  [P in keyof T]?: T[P] extends (infer U)[]
    ? RecursivePartial<U>[]
    : T[P] extends object ? RecursivePartial<T[P]> : T[P]
};

This results in TypeScript requiring one to define all playground options not just the ones that you want to override from defaults.

To reproduce just attempt to create an instance of ApolloServer with playground options not setting all available options:

const server = new ApolloServer({
    playground: {
        settings: {
            "request.credentials": "include",
        },
    }
});

Failure to provide all options results in:

Types of property 'settings' are incompatible.
Argument of type '{ playground: { settings: { "request.credentials": string; }; }; }' is not assignable to parameter of type 'Config'.
  Types of property 'playground' are incompatible.
    Type '{ settings: { "request.credentials": string; }; }' is not assignable to type 'boolean | RecursivePartial<RenderPageOptions> | undefined'.
      Type '{ settings: { "request.credentials": string; }; }' is not assignable to type 'RecursivePartial<RenderPageOptions>'.
        Types of property 'settings' are incompatible.
          Type '{ "request.credentials": string; }' is not assignable to type 'ISettings'.
            Property ''general.betaUpdates'' is missing in type '{ "request.credentials": string; }'.

TypeScript version: 3.0.3.

🛹 playground 🧬 typings

Most helpful comment

Something like this...

return new ApolloServer({ playground: {...defaultPlaygroundOptions, settings: { ...defaultPlaygroundOptions.settings, "request.credentials": "include", } },

All 12 comments

from a quick look the RecursivePartial seems incorrect, should work with

type DeepPartial<T> = { [P in keyof T]?: DeepPartial<T[P]>; };

at least on the latest TS 3.1

Having the same issue. Is there currently a work around available for this besides just marking it to ignore?

Something like this...

return new ApolloServer({ playground: {...defaultPlaygroundOptions, settings: { ...defaultPlaygroundOptions.settings, "request.credentials": "include", } },

RecursivePartial looks so obscure and complex that I can't help but feel there is a simpler alternative. This problem surely demonstrates that 😄

Is anyone still experiencing this? Fix is:

type RecursivePartial<T> = {
  [P in keyof T]?: T[P] extends (infer U)[]
    ? RecursivePartial<U>[]
    : T[P] extends (object | undefined) ? RecursivePartial<T[P]> : T[P]
};

Where T[P] extends (object | undefined) is in place of T[P] extends object above. But it seems to only affect older versions of AS, no clue why as the types haven't really changed.

In the playground

Closing this for now. If someone is still experincing issues we can apply that patch, but as I said earlier it seems not to affect recent versions of AS.

@JacksonKearl FWIW, I'm using apollo-server-express 2.6.5 and TypeScript 3.4.3 and I'm seeing this problem.

Interesting, do you think you could try manually updating the RecursivePartial type to the above in packages/apollo-server-core/src/playground.ts to see if that fixes it?

@JacksonKearl what's the proper way to rebuild the apollo-server-core package after making the above change? I created a tsconfig.json file in node_modules/apollo-core-server and run tsc which gave me a "cannot find module "mock-req" so I just moved that folder and tried to rebuild but I'm getting:

➜  apollo-server-core git:(master) ✗ tsc
src/playground.ts:73:9 - error TS2322: Type '{ settings: { 'general.betaUpdates': boolean; 'editor.theme': Theme; 'editor.cursorShape': CursorShape; 'editor.reuseHeaders': boolean; 'tracing.hideTracingResponse': boolean; 'queryPlan.hideQueryPlanResponse': boolean; 'editor.fontSize': number; 'editor.fontFamily': string; 'request.credentials': string; } | { ...;...' is not assignable to type 'RenderPageOptions'.
  Type '{ settings: { 'general.betaUpdates': boolean; 'editor.theme': Theme; 'editor.cursorShape': CursorShape; 'editor.reuseHeaders': boolean; 'tracing.hideTracingResponse': boolean; 'queryPlan.hideQueryPlanResponse': boolean; 'editor.fontSize': number; 'editor.fontFamily': string; 'request.credentials': string; } | { ...;...' is not assignable to type 'RenderPageOptions'.
    Types of property 'schema' are incompatible.
      Type 'RecursivePartial<IntrospectionResult> | undefined' is not assignable to type 'IntrospectionResult | undefined'.
        Type 'RecursivePartial<IntrospectionResult>' is not assignable to type 'IntrospectionResult'.
          Property '__schema' is optional in type 'RecursivePartial<IntrospectionResult>' but required in type 'IntrospectionResult'.

73   const playgroundOptions: PlaygroundRenderPageOptions = {

Thanks,
-Steve

Ah! Do you have strictNullChecks enabled? That seems to be the culprit here, as with that enabled an object | undefined will no longer extends object. Demo playground. You can flip strictNullChecks in the options and the first config will flip between valid and invalid.

@JacksonKearl ok I got it to build. Here's my playground config:

    playground: {
      settings: {
        "editor.theme": "light"
      }
    },

Which is now causing this error:

Type '{ settings: { "editor.theme": string; }; }' is not assignable to type 'boolean | RecursivePartial<RenderPageOptions> | undefined'.
  Type '{ settings: { "editor.theme": string; }; }' is not assignable to type 'RecursivePartial<RenderPageOptions>'.
    Types of property 'settings' are incompatible.
      Type '{ "editor.theme": string; }' is missing the following properties from type 'ISettings': 'general.betaUpdates', 'editor.cursorShape', 'editor.reuseHeaders', 'tracing.hideTracingResponse', and 3 more.

If you check #3010, there are two changes that need to be made: first the type definition needs to be changed to the extends (object | undefined), and second playgroundOptions needs to be coerced to any, as the types aren't actually quite accurate right now. So the first error you got regarding __schema being optional is actually a correct error.

Was this page helpful?
0 / 5 - 0 ratings