JavaScript uses dynamic typing, which does not check the type at compile time and allows the runtime to determine whether the type is wrong when it is actually executed. This feature is a bit like the calculation in assembly, where the type is weak and different types are always explicitly and implicitly converted.

In an ordinary Todo in the Demo type may not be that important, and when the project became big, inside there are a lot of different logic, as a project by another person to take over, reading is very troublesome, because always the type of each variable to see the code context (custom types or primitive types), in general, You can see this in console.log, but it’s a temporary fix.

Of course, strongly typed JavaScript is already mature in TypeScript, but not all projects are written in TS from the start. There are pure JS projects, so how do you maintain typing in those projects?

The answer is to use JSDoc under VSCode; VSCode will do its best to derive the type.

What is the JSDoc

JSDoc is basically a code comment, a comment that indicates the type of value in JavaScript, and a comment to your code, usually a comment that starts with the @ character in your code. That’s JSDoc. Here is a simple example

/** * add * @param {Number} x * @param {Number} y * @returns {Number} */
function add(x, y) {
    return x + y; 
}
Copy the code

At @param, @returns, the arguments x and y and the return value of the function are specified.

To explicitly enable JS type checking, see vscode-type-checking:

If you open the type check, you can see that there is an error when passing in arguments of other types. Once you have filled in the correct values, VSCode now knows what type z is (since x and y are numbers, x + y is also a number).

Code completion prompts can be implemented:

Annotate basic types in code

@param, String Number Array Object, etc. Such as:

/** * * @param { Array
      
        } numbers * @param { String[] } names */
      
function test(numbers, names) {
    names.forEach(name= > {
        // ... })}Copy the code

String[] is the same as Array

, representing an Array of strings, and VSCode can also automatically complete forEach and name (string.pototype).

The following example represents a custom object:

/** * say hello * @param { { name: String } } person */
function sayHello(person) {
    console.log(person.name); 
}
Copy the code

@param specifies the type of the argument to the function; Returns Specifies the type of the function.

Annotate custom types

In fact, there is an explanation for custom types in the above example (the object one), but the above example is for literal declarations. Now let’s look at VSCode’s handling of JavaScript classes.

class Person {
    /** * Person * @param { String } name */
    constructor(name) {
        this.name = name; 
    }

    /** * @returns { Person } */
    sayHello() {
        console.log('Hello, i am'.this.name); 

        return this; 
    }

    /** * @param { Person } friend * @returns { Person } */
    playWith(friend) {
        this.sayHello(); 
        console.log('and i will play with', friend.name); 

        return this; }}Copy the code

Here we declare the Person class with the method sayHello and a name attribute. From VSCode’s point of view, this is also a type that can be used as an argument to @param (playWith function above).

Incidentally, the syntax for type annotations in JSDoc comes primarily from type expressions in Google Clojure Compile.

Generics (limited)

JSDoc also offers generics of some capability, but they are very limited and not nearly as good as true generics.

Going back to the example of add(x, y), if x and y are limited to numbers, does the addition of string x and y need to be rewritten as add? Actually, no, you can use @template to do this.

/** * add * @template T * @param {T} x * @param {T} y * @returns {T} */
function add(x, y) {
    return x + y; 
}
Copy the code

Here T is introduced to understand the JSDoc as follows:

  1. xyAre all types ofT, indicating that they are of the same type and return the same value.
  2. If there is no@templateThe @template declaration here states that T is “generic”, which is a special variable that is only used to represent types, not values

After using @template:

This shows that the types of D and z can only be deduced after VSCode understands the JSDoc of Add, while T seems to be a variable, in both cases string and number respectively.

.d.ts

*.d.ts files are another way to annotate types. Common JavsScript libraries do not have type annotations, which will not be compatible with TypeScript type checking. Therefore, d.ts should be introduced to describe the types of js libraries so that TS can use them.

Of course, VSCode can read it and make it easy to develop. Write the test. Js:

/** * @param { Person } p */
function test(p) {}Copy the code

Then write the type description test.d.ts for Person

declare interface Person {
    name: string, age? :number, 
    sayHello: (a)= > Person, 
    playWith: (friend: Person) = > Person
}
Copy the code

Note: The question mark of age means that age is optional.

VSCode will then find the *.d.ts file and read it to get the type information:

Refer to the link

http://www.css88.com/doc/jsdoc/about-block-inline-tags.html https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler#type-expressions https://code.visualstudio.com/Docs/languages/javascript#_type-checking https://zh.wikipedia.org/wiki/JavaScript