preface

TypeScript is not new to people on the front end or even to people in the back end. Today we are going to talk about TypeScript, its basic usage, and how it is used in projects. By the way, TS is too big, because its types can be flexibly combined, but rest assured, this paper will not involve too many conceptual things (also can not finish), because in fact, in a big project, it is usually these basic types, such as type and interface, but also by position. If you’re the project leader or the head of the front end of your company and you’re really demanding or you’re writing tools, encapsulating common components, there’s a lot more opportunity to use those special things

In TS, it is best to specify the type as much as possible, because it is used to regulate their own team, if you use any, it is better to use js, if you only have your own project, then there is no need to use this stuff, and make trouble for yourself

The base type

Nerver, void, number, number, number, number, number, number, number, number, number, string, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number So let’s just do a quick list here

Basic types: number/string, Boolean/Array/object

Any null, undefined void never

tool

Since we need to compile TSC files every time we do experiments, and node files are too troublesome, I simply wrote gulp(not webpack because gulp is easier and faster), you can use it directly

In the comments section, someone pointed out that tSC-w can be directly compiled, which is actually the same, but I mainly want to make it easier for me to clear the screen when I watch, as well as all other file operations, so gulp is more convenient. I will leave a shelf here. If you are interested, you can find more convenient commands in the comments section or gulp official website

Usage:

  1. cnpm i -g gulp-cli– Install gulp itself
  2. cnpm i– Install local dependent libraries
  3. gulp watch– Run the watch task of gulp

package.json

{
  "name": "test"."version": "1.0.0"."main": "index.js"."license": "MIT"."dependencies": {
    "gulp": "^ 4.0.2." "."gulp-clean": "^ 0.4.0"."gulp-run": "^ 1.7.1." "."gulp-typescript": 1 "" ^ 6.0.0 - alpha.."gulp-watch": "^ 5.0.1." "."typescript": "^ 3.7.4." "}}Copy the code

gulpfile.js

const gulp = require('gulp'),
  watch = require('gulp-watch'),
  ts = require('gulp-typescript'),
  run = require('gulp-run'),
  clean = require('gulp-clean');

gulp.task('watch', () = > {return watch('./1.ts', () => {
    gulp
      .src('./1.ts')
      .pipe(
        ts({
          target: 'ES6'.outFile: '1.js'.experimentalDecorators: true,
        }),
      )
      .on('error', err => {
        // console.error(err);
      })
      .pipe(gulp.dest('build'))
      .pipe(run('node build/1.js'));
  });
});

Copy the code

The project structure is as follows

The results

Instead of creating the build manually, run gulp directly and it will be created and run automatically

An array of

Arrays have a lot of tricks, but here’s how to use them, and then we’ll talk about how to work with other things

let arr = Array<number>; // Specifies only an array of numbers
// let arr = number[];
Copy the code

Type – Interface

I am often asked what is the difference between TS type and interface. First of all, I must be sure that there are similarities and differences between these two functions, otherwise the author would not be wrong to make two out. Here we first say the use of respectively, and then the difference

Let’s assume that these are both custom types

First of all, the TS convention type can be specified inside json, which you all know is going to be like this and this is going to be an error

Strictly abide by it

type

But if you have a type that you’re going to use a lot, like a user type, and you’re going to have a name and an age, you’re not going to write a bunch of them every time you define a variable

So you can use it in multiple places

interface

The above example would be the same if you changed it to interface

The difference between

In fact, if you look at this example, you might think, well, it’s not the same, what’s the difference

interface
It needs to be implemented

Imagine that I have a requirement, and I have a class that encapsulates HTTP requests, and I can send the data directly to the server as a string and then I can get it back and parse it into JSON, but before I do that, let’s talk about another thing

implements

Implements is a bit like extends, which extends from a class. Instead of inheriting a class, implements an interface

So let’s do an example with interface

interface serializeable {
  tostring(): string;
  fromString(str: string) :void;
}

class SendData implements serializeable {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  public tostring() {
    return JSON.stringify({
      name: this.name,
      age: this.age,
    });
  }

  public fromString(str: string) {
    let data = JSON.parse(str);
    this.name = data.name;
    this.age = data.age; }}Copy the code

By the way, implements implements multiple interfaces at once, just by name, like this

interface serializeable {
  tostring(): string;
  fromString(str: string) :void;
}

interface serializeable2 {

}

class SendData implements serializeable, serializeable2 {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  public tostring() {
    return JSON.stringify({
      name: this.name,
      age: this.age,
    });
  }

  public fromString(str: string) {
    let data = JSON.parse(str);
    this.name = data.name;
    this.age = data.age; }}Copy the code

See this… I’m sure some people still have questions. So… How exactly does this thing work

Let’s try this with reference to the HTTP requirements we mentioned above, assuming that the data to be sent to the server now has to implement my interface

interface serializeable {
  tostring(): string;
  fromString(str: string) :void;
}

class SendData implements serializeable {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  public tostring() {
    return JSON.stringify({
      name: this.name,
      age: this.age,
    });
  }

  public fromString(str: string) {
    let data = JSON.parse(str);
    this.name = data.name;
    this.age = data.age; }}function sendToServer(obj: serializeable) {}

sendToServer(new SendData('name'.18));

Copy the code

There’s nothing wrong with looking at the console at this point

But let’s just arbitrarily switch classes

SendData2 didn’t implement my interface, so it just exploded. How does that help? Note that ⚠️ is useful for error detection. Normally, if you write in JS, you need to execute obj. Tostring in sendToServer or any other method of this interface to save the file. This will become a runtime error. So it’s nice that this thing just avoids some of the mistakes, right?

The generic

Generics are a little bit more special, so let’s look at an example, just to give you a sense of what this is all about. So I’m going to write a function, regardless of practicality, which is a function that passes in a number, the number of cycles, and returns an array of numbers

function repeat(item: number, count: number) :number[] {
  let result: number[] = [];

  for (let i = 0; i < count; i++) {
    result.push(item);
  }

  return result;
}

let arr: number[] = repeat(13.4);
console.log(arr);

Copy the code

First things will come out, but… Repeat, now we only implement loop numbers, is it possible that in the future we will need to loop strings, booleans, and how much do we need to write them one by one so we have to find a way to pass the type, of course any can also be used, but… So if you use any in the introduction that I wrote you can just use JS and of course, this is just generics, but you can use any here as well

function repeat<T> (item: T, count: number) :T[] {
  let result: T[] = [];

  for (let i = 0; i < count; i++) {
    result.push(item);
  }

  return result;
}

let arr: number[] = repeat<number> (13.4);
console.log(arr);

let arr2: string[] = repeat<string> ('aaa'.4);
console.log(arr2);
Copy the code

Is it easy?

In fact, if this looks familiar to you, yes, in TS an Array is a generic, like Array

and just to introduce another concept

Type conjecture

This is just our example, in fact, directly do not pass type, but also can come out

Ts are very smart, he can, depending on the type of you coming to speculate what type you are, of course, the Jane Jane, a little more complicated, such as a generic class, declared within an array, then the add method, for the first time is digital, the second is the string that he couldn’t speculate, too much not sure. Actually this generic speaking, is very huge, this if you are interested can leave a message or comment on a single chapter dedicated open it, because there are some variants of this generic, for example, there are more than two generics, three, respectively, in where, and can also have optional type, replace type, the type of joint, cross type, There’s a lot of weird stuff out there, so… If you are interested, please leave a message

A decorator

The decorator actually it is like to use my personal, he can directly give class to add some functionality Actually there is someone there may be a doubt, why do I want to use this thing, I directly add not just finished yao, also save trouble, actually can imagine, now need to use the user data is attached to this class, I must first point, It is possible to add one by one, but it is trouble. As the saying goes, laziness is the greatest power to advance human progress. In fact, if you know about Vue 2.x TS, you should know that it is full of decorators. (By the way, the message released by VUe3 is that the decorator is discarded, probably because it is an experimental feature for the time being, the details need to be informed later.)

How to write a simple decorator

Class decorator

The decorator is just a function, and you just add an @ sign to the class, and you have to pay attention to the arguments, or ts will give you an error

Note that ⚠️ fn only has one argument for class decorators, not for properties and methods, as discussed below

function fn(target){}@fn
class User {

}
Copy the code

By the way, if you’re using vscode or some other editor, it might give you an error, right

{
  "compilerOptions": {
      "target": "ES5"."experimentalDecorators": true}}Copy the code

If I write this, I won’t get an error

The target is actually the constructor of our class

function fn(target) {
  console.log(target);
  target.a = 12;
}

@fn
class User {}

console.log(User.a);

Copy the code

If you look at the result, you’ll see that an error has been reported and the result has been returned, which is very strange

In fact, ts is very strict, it must be used at initialization, runtime is fine, the results are fine, but I just can’t detect that… What to do? It’s easy, we can just define this property on our class, like this

function fn(target) {
  console.log(target);
  target.a = 12;
}

@fn
class User {
  static a: number;
}

console.log(User.a);

Copy the code

If you run it again, no errors will be reported

Decorator parameter passing

The target (constructor) parameter is passed inside the function returned by the constructor function. The outermost layer is the parameter passed in

function fn(num:number) {
  return function(constructor: Function){
    constructor.prototype.a = num
  }
}

@fn(12)
class User {
  a: number;
}

let obj = new User();
console.log(obj.a);

Copy the code

See at run time

Now, let’s write two classes, and we can pass parameters to distinguish them

function fn(num:number) {
  return function(constructor: Function){
    constructor.prototype.a = num
  }
}

@fn(12)
class User {
  a: number;
}

let obj = new User();
console.log(obj.a);

@fn(5)
class User2 {
  a: number;
}

let obj2 = new User2();
console.log(obj2.a);


Copy the code

Results:

That’s great, isn’t it

The advanced

In fact, decorators have been able to meet most people’s work needs up to the last step, because this thing

  1. It’s an experimental thing
  2. It’s rarely used at work

However, there are a few interesting things to share with you

Preface: We this class, certainly do not know an instance right, so next, let’s write so, a direct attribute a little trouble, but… What if it’s JSON? Let’s look at an example

Now that I’ve changed it to JSON, there’s nothing wrong with that. Now what

Prototype this way is not complete, so don’t use this decorative food pass to picture the project, it will kill people. But what to do… I don’t want to add it to anyone, so I can just say it’s the right thing to do, and I can just rewrite that class, but there’s a problem, and I can’t just copy the code and do it again, so I can just add the code

function fn(num: number) {
  return function<T extends {new(... arg:any[]) : {}} > (constructor: T) {
    return class extends constructor {
      json: object = { a: num };
    };
  };
}

@fn(12)
class User {
  json: {
    a: number;
  };
}

let obj = new User();
obj.json.a = 80;
console.log(obj.json);

let obj2 = new User();
console.log(obj2.json);

Copy the code

At this point, there is no problem ~ is not very simple of course… Put your knife down, and some of you might say, wait, wait, wait, wait, wait, wait, wait, wait, wait, wait, wait, wait. Arg :any[]):{}}>

Well, actually, let’s get rid of this and take a look

But direct write T also not line, just say, let’s the T to inherit an interface, and the interface is not a common interface, need is a dynamic interface, so you need to dynamically create a function Is the new code above () and, what is this parameter, so take out all the new (… Args :any[]) this extends {new(…).

Ok, that’s all for this ts tutorial. If you have any questions, please feel free to comment in the comments section. Or you can add my QQ and wechat to communicate with us.

916829411
Copy the code

WeChat:

Dyy916829411
Copy the code