Structured Text with Typescript

I was able to solve this issue without introducing additional login in the application code.
It involves some extra configuration, but hopefully it will help ppl looking for a solution:

What we need to do is merge DatoCMS schema with custom one, that will override StructuredText value. That can be done by utilising schema loader:

graphql.config.ts

  schema: {
    'https://graphql.datocms.com': {
      headers: {
        Authorization: process.env.DATOCMS_CLIENT_TOKEN!,
        'X-Exclude-Invalid': 'true'
      },
      loader: './schema-loader.js'
    }
  },

schema-loader.js

const {loadSchema} = require('@graphql-tools/load')
const {mergeTypeDefs} = require('@graphql-tools/merge')

module.exports = async (schemaString, config) => {
  const schema = await loadSchema(schemaString, config)

  return mergeTypeDefs(
    [
      `
        scalar StructuredTextDocument
        type BlogpostModelContentField {
          value: StructuredTextDocument!
        }
      `,
      schema
    ],
    {
      // if conflict is detected, use custom definition
      onFieldTypeConflict: (customField, _schemaField) => {
        return customField
      }
    }
  )
}

We introduce a custom scalar value and use it to override JsonField. In the config, we need to include needed import that will be added to generated types:

graphql.config.ts

generates: {
    'src/types/graphql.ts': {
      plugins: [
        {
          add: {
            content:
              "import { type Document as StructuredTextDocument } from 'datocms-structured-text-utils';"
          }
        },
        'typescript',
        'typescript-operations'
      ],
      config: {
        strictScalars: true,
        scalars: {
          StructuredTextDocument: 'StructuredTextDocument',
          // and others...
        }
      }
    }
  }

All this results in proper types being generated. No need for type guards or type overriding in the app code.

3 Likes