当前位置:网站首页>Are you still writing the TS type code

Are you still writing the TS type code

2022-07-05 01:03:00 TNTWEB

As a front-end Developer , Developing ts Project time , The most tedious work should be the data type and mock data , Because if this part of the work is not done , Business logic is written later , If you do, it's all copy and paste similar repetitive work , It takes a lot of time . The following will introduce an automatic generation ts The type and mock Method of data , Help students get rid of tedious work .

Below we will use an example , Let's understand the basic process of code generation .

TS Basic process of code generation

Let's take the following paragraph ts Code, for example , Let's talk about the basic process of generating it .

export interface TestA {
  age: number;
  name: string;
  other?: boolean;
  friends: {
    sex?: 1 | 2;
  },
  cats: number[];
}

First step : Select data source

Let's think about a question first , Write the above code interface What information is needed to generate ?

Through analysis , We first need to know how many properties it has , Then you need to know which attributes are necessary , In addition, you need to know the type of each attribute 、 Enumeration and other information . There is a data format that can perfectly provide us with the data we need , It is JSON Schema.

Students who have contacted the back end should have known JSON Schema, It's right JSON Description of the data , for instance , We defined the following JSON structure :

{
  "age": 1,
  "name": " test ",
  "friends": {
          "sex": 1
  },
  "cats": [
    1,
    2,
    3
  ],
  "other": true
}

Let's verbally describe this json: It has age、name、friends、cats、other5 Attributes ,age The type of property is number,name The type of property is string,cats The type of property is number Composed of arry,friends Property is a object, It has one sex attribute , The type is number ,other The type of property is boolean.

use JSON Schema Is described as follows :

{
  "type": "object",
  "properties": {
    "age": {
      "type": "number"
    },
    "name": {
      "type": "string"
    },
    "cats": {
      "type": "array",
      "items": {
        "type": "number"
      }
    },
    "friends": {
      "type": "object",
      "properties": {
        "sex": {
          "type": "number"
        },
        "required": [
          "e"
        ]
      }
    },
    "other": {
    "type": "boolean",
    },
    "required": [
      "a",
      "b"
    ]
  }
}

It can be seen that JSON Schema Our oral description can be perfectly programmed , This is a simple example ,JSON Schema The ability to describe is much more than that , such as enumeration , The maximum length of an array , The maximum and minimum values of numbers , Is it necessary And so on, our commonly used attributes can accurately describe , Therefore, it is also commonly used in the scenario of user input verification .

The second step : Select the code generation tool

You see the title , I believe most students already know the answer , you 're right , Namely TS AST and TS Compiler API, The latter can generate or modify TS AST, You can also output compiled files . Let's take a look at how to use TS Compiler API Generate an abstract syntax tree and compile it into the code mentioned above .

Corresponding TS Compiler The code is as follows :

factory.createInterfaceDeclaration(
    undefined,
    [factory.createModifier(ts.SyntaxKind.ExportKeyword)],
    factory.createIdentifier("TestA"),
    undefined,
    undefined,
    [
      factory.createPropertySignature(
        undefined,
        factory.createIdentifier("age"),
        undefined,
        factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword)
      ),
      factory.createPropertySignature(
        undefined,
        factory.createIdentifier("name"),
        undefined,
        factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
      ),
      factory.createPropertySignature(
        undefined,
        factory.createIdentifier("other"),
        factory.createToken(ts.SyntaxKind.QuestionToken),
        factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword)
      ),
      factory.createPropertySignature(
        undefined,
        factory.createIdentifier("friends"),
        undefined,
        factory.createTypeLiteralNode([factory.createPropertySignature(
          undefined,
          factory.createIdentifier("sex"),
          factory.createToken(ts.SyntaxKind.QuestionToken),
          factory.createUnionTypeNode([
            factory.createLiteralTypeNode(factory.createNumericLiteral("1")),
            factory.createLiteralTypeNode(factory.createNumericLiteral("2"))
          ])
        )])
      ),
      factory.createPropertySignature(
        undefined,
        factory.createIdentifier("cats"),
        undefined,
        factory.createArrayTypeNode(factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword))
      )
    ]
 )

At first glance, generating this simple type of code is very complex , But take a closer look, if these methods are encapsulated , The code will be much simpler , And there are already some mature third-party libraries , such as ts-morph etc. .

Ts Compiler Api Only English documents , And it's complicated to use , Moreover, we are not sure which function needs to be called to generate different types of code , But we can go TS AST View Inquire about , It can be based on what you enter TS The code generates the corresponding abstract syntax tree and Compiler Code , The above code is TS AST View Provided .

factory.createInterfaceDeclaration Method will generate a interface node , Generated after , We also need to call a method that will generate interface Print out , Output to string file , The reference codes are as follows :

// ast Transfer code 
//  Need to add the above factory.createInterfaceDeclaration The generated node is passed in 
export const genCode = (node: ts.Node, fileName: string) => {
    const printer = ts.createPrinter();
    const resultFile = ts.createSourceFile(fileName, '', ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
    const result = printer.printNode(
        ts.EmitHint.Unspecified,
        node,
        resultFile
    );
    return result;
};

The third step : Beautify the output code

We should be familiar with beautifying the code , I believe we all have Prettier, Necessary tools for each front-end project , It can not only directly format the file we are writing , You can also format the string code we passed in manually , Don't talk much , Code up :

import * as prettier from 'prettier';

//  default prettier To configure 
const defaultPrettierOptions = {
    singleQuote: true,
    trailingComma: 'all',
    printWidth: 120,
    tabWidth: 2,
    proseWrap: 'always',
    endOfLine: 'lf',
    bracketSpacing: false,
    arrowFunctionParentheses: 'avoid',
    overrides: [
        {
            files: '.prettierrc',
            options: {
                parser: 'json',
            },
        },
        {
            files: 'document.ejs',
            options: {
                parser: 'html',
            },
        },
    ],
};

//  Format beautification file 
type prettierFileType = (content:string) => [string, boolean];
export const prettierFile: prettierFileType = (content:string) => {
    let result = content;
    let hasError = false;
    try {
        result = prettier.format(content, {
            parser: 'typescript',
            ...defaultPrettierOptions
        });
    }
    catch (error) {
        hasError = true;
    }
    return [result, hasError];
};

Step four : Write the generated code to our file

This step is relatively simple , Directly yes node Provided fs Api Generate a file , The code is as follows :

//  Create directory 
export const mkdir = (dir:string) => {
    if (!fs.existsSync(dir)) {
        mkdir(path.dirname(dir));
        fs.mkdirSync(dir);
    }
};
//  Writing documents 
export const writeFile = (folderPath:string, fileName:string, content:string) => {
    const filePath = path.join(folderPath, fileName);
    mkdir(path.dirname(filePath));
    const [prettierContent, hasError] = prettierFile(content);
    fs.writeFileSync(filePath, prettierContent, {
        encoding: 'utf8',
    });
    return hasError;
};

Front and rear end coordination

The above process still lacks an important step : data source JSON Schema Who provides ?

This requires collaboration between the front and rear ends , At present, the back-end has a very mature generation JSON Schema Tools for , such as Swagger,YAPI etc. .

Access Swagger All back-end system projects can provide... To the front-end swagger.json file , The contents of the file include the detailed data of all interfaces , Include JSON Schema data .

YAPI and Swagger Different , It is API Centralized management platform , Managed on it api We can get all the information through the interface it provides api Detailed data , and swagger.json The content provided is similar , and YAPI The platform supports importing or generating swagger.json.

If there is an interface management platform and relevant specifications are formulated , The efficiency of front and back-end cooperation will be improved a lot , Reduce communication costs , Moreover, the front-end can also do some work related to engineering efficiency based on the management platform .

Overcome the difficulties

The above steps are just a brief introduction to generation ts An idea of type code , There are still some difficulties to be solved under this idea , such as :

  • In actual development, we need comments , but TS Compiler API Cannot generate comments : We can solve this problem by re coding string After generation, it is solved by manually inserting notes in the corresponding places .
  • The type of actual business can be very complex , The nesting level is deep : This problem can be solved by recursive function .
  • Generated type code , If API There are changes , What to do , Or new API To be placed in a file with the original generated , How to deal with this situation ?TS ComPiler API Can read the source file , Even existing files can be read , We can read the source file and then use Compiler API Modify its abstract syntax tree to realize the function of modifying or adding types .
  • The coordination of front and rear ends : This needs to find leader It's solved .

summary

After the four steps mentioned above , We learned the basic process of generating code , And the implementation scheme of each step is not fixed , You can choose :

  • On the issue of data source selection , We have nothing but JSON Schema You can also choose the original json Data as a data source , It's just that the generated type is not so accurate , Recommend a good website here :JSON2TS.
  • We can also use some common template engines to generate code generation tools , such as Nunjucks,EJS etc. , They can not only generate HTML, It's fine too Generate files in any format , And can return the generated string .
  • Code beautification is still recommended prettier.
  • For the front end , At present, the best way to output files is Node 了 .
This paper only provides an engineering generation method TS type 、Mock Data and other simple and reproducible code , After implementation, it can reduce some labor-intensive Work content of , Let's focus more on business logic development .

reference

原网站

版权声明
本文为[TNTWEB]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202141058433689.html