preface

TypeScript + React type safety consists of three components: Component, Redux, and Service typing.

Service – Graphql typed

Graphql is an interface query language launched by Facebook — one of the mature and mainstream technology solutions for front and back end interaction.

Graphql positioning

It was around September 19 that I decided to use Graphql in a technical exploration project — but I still didn’t have a satisfactory technical solution on how to integrate Graphql into the “type-safe three-piece” technology architecture.

In React, the classical use of Graphql includes converting Graphql Schema and Query to higher-order components or Hooks, which actually broke the basic technical solution of one-way data stream [Redux + useReducer] that I was pushing hard at that time.

Finally, after much thought, I decided to position Graphql as one of the alternatives to Restful apis, and to recognize and process it as a pure Service layer, so that Graphql can be integrated seamlessly with minimal conflict with the existing basic technical solutions.

Typing of Graphql

Graphql itself

As deep users of TypeScript, we’d like to write Graphql with static type detection — structure, type, etc. — and we’d like a way to detect and throw out low-level errors in real time.

Fortunately, similar to TypeScript, there is a Graphql Language Server that uses Schema to detect errors in our Query statements.

Using the VSCode editor as an example, we can:

  • Install prisma. vs code-GraphQL plug-in
  • Install the watchman
  • Configure.graphqlConfig in the project root directory, for example:
{"schemaPath": "schema.graphql", // @imp: "schemaPath":" schema.graphql", // @imp: "**/*", or not "includes": ["**/*.graphql", "**/*.gql"], "excludes": ["node_modules"], "extensions": { "endpoints": { "dev": "Http://127.0.0.1/graphql", "prod" : "http://www.naotu.com/graphql"}}}Copy the code

This enables real-time static detection of Query statements.

The problem with this plugin is that it does not dynamically monitor schema changes — shema changes, and may need to restart vscode for a while.

gen Service

Similarly, we need a tool to convert interface documentation schemas and written Query statements into TypeScript Service invocation code. There are also open source solutions and tools for this @graphqL-codeGen.

Install dependencies:

npm i -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-graphql-request
Copy the code

Configuration codegen. Yaml:

schema: ./schema/schema.graphql
documents: ./src/**/*.graphql
generates:
  src/models/service.ts:
    plugins:
      # Introduce this plug-in to generate conforming Service code
      - 'node_modules/@bit/ks-ef-common.graphql-codegen-tkit-plugin'
    config:
      operationResultSuffix: Res
  src/models/types.d.ts:
    plugins:
      - typescript
      - typescript-operations
    config:
      globalNamespace: true
      flattenGeneratedTypes: true
      exportFragmentSpreadSubTypes: true
      # immutableTypes: true
      # avoidOptionals: true
      operationResultSuffix: Res
Copy the code

Since the default @graphql-codegen/ typescript-graphqL-Request Service template is not required for the underlying technical solution, So the graphql-codegen-tkit-plugin changes typescript-GraphqL-request:

const {
  GraphQLRequestVisitor,
  validate,
  plugin
} = require('@graphql-codegen/typescript-graphql-request');

const TypeTpl = `import { NonStandardAjaxPromise, ExtraFetchParams } from '@tkit/ajax'; `;

const newPlugin = function() {
  // eslint-disable-next-line prefer-rest-params
  const args = [].slice.call(arguments.0);
  // eslint-disable-next-line prefer-spread
  const { prepend, content } = plugin.apply(null, args);
  return {
    prepend: prepend.map(i= > i.replace(/graphql-request/g.'@tkit/ajax/lib/graphql')),
    content:
      TypeTpl +
      content
        .replace(/\): Promise</g.', opt? : ExtraFetchParams): NonStandardAjaxPromise<')
        .replace(/variables\)/g.'variables, opt)')
        .replace(/graphql-request/g.'@tkit/ajax/lib/graphql')
        .replace(/ / \ [.'(')}; };module.exports = {
  GraphQLRequestVisitor,
  plugin: newPlugin,
  validate
};
Copy the code

Add “GQL “:” graphqL-codeGen “to package.json

npm run gql
Copy the code

You can generate typed Service code

Service. Ts sample:

import { GraphQLClient } from '@tkit/ajax/lib/graphql';
import { print } from 'graphql';
import gql from 'graphql-tag';
import { NonStandardAjaxPromise, ExtraFetchParams } from '@tkit/ajax';
export const DocumentFragmentDoc = gql` fragment Document on Doc { id name owner type is_shared parent_id modify_time snapshot_id } `;
export const DocListDocument = gql` query docList($id: String! , $withDocId: Boolean = false) { doc(id: $id) @include(if: $withDocId) { ... Document } docList(id: $id) { ... Document } }${DocumentFragmentDoc}
`; .Copy the code

Types. Which s example:

export type Maybe<T> = T | null;
/** All built-in and custom scalars, mapped to their actual values */
export interface Scalars {
  ID: string;
  String: string;
  Boolean: boolean;
  Int: number;
  Float: number;
}

export interface DocDocSnapshotArgs {
  id: Scalars['String']; }...Copy the code

The resources

  • vscode-graphql
  • @graphql-codegen
  • @divyenduz/ ts-graphqL-plugin A TypeScript plugin