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