Abstract: INTRODUCTION to TS.

  • TypeScript for the first time
  • Author: Xu Qi

FundebugReproduced with authorization, copyright belongs to the original author.

Why TS?

To be honest, I didn’t want to use TS in real projects at first, because I felt that “genre” would limit the advantages of JS (well, it’s a cliche); Second, when I heard the sour taste of TS + Redux, I was a little discouraged. Third, TS environment use library need to add type declaration, many libraries do not support, a bit worried about the smoothness of the push…

That’s when you need an invisible force to push you. What pushed me is that the team is increasingly popularizing TS, and I hope this article will push you

Next, the React + TS project will be used as the background to introduce some problems I encountered in the initial TS development project. I hope it will be helpful to you.

How to elegantly declare type

1. The basic

JS has one more type declaration than JS. The old man lifted up his sleeve and carried the keyboard is a shuttle:

interface Basic {
  num: number;
  str: string | null; bol? : boolean; }Copy the code

The five JS value types are easily declared. What about arrays and functions? To:

interface Func {
  func(str: string): void;
}

interface Arr {
  str: string[];
  mixed: Array<string | number>;
  fixedStructure: [string, number];
  basics: Basic[];
}
Copy the code

In addition, you can also define your own type, such as the common callback function, the declaration should specify the type of the callback function:

event.on('change'.function() {});
Copy the code

So how does this on method need to be declared? Try Function as cb Function type

on(type: string, cb: Function) : {}Copy the code

Then congratulations, you’ll get a TSLint error:

Fortunately, this error tells you what to do: Declare a dedicated function type:

type Cb = (a)= > void;

on(type: string, cb: Cb);
Copy the code

At this point, our TS life is beginning 👏👏👏

Enumerations are also common, such as declaring the states of a state machine:

enum Status {
  Draft,
  Published
}

// A value can also be specified
enum Status {
  Draft = 'Draft',
  Published = 'Published'
}
Copy the code

When using enumerations, there are often requirements on how to convert enumerations to original data types. For example, the status requested by the interface is a Draft string, but the status declared in the code is an Enum type.

// string to enum
const str = 'Draft';
const status: Status = Status[str];

// enum to string
Status[Status.Published] === 'Published'
Copy the code

Mix of 2.

Separate type or interface declarations may not seem that difficult, but how about mixing them up in a project?

  • There may be dozens of type declarations;
  • Type declarations may appear in interface input and output parameters, in Props and State of the React component, or in function methods.
  • When a project is large enough to abstract out separate libraries, the type needs to be abstracted;
  • .

You may encounter situations that break your grip on TS. What to do?

First, let’s talk about our practical conclusions: independent declaration, nearby declaration, grouping by responsibility, eliminating “hard” association, limited abstraction.

– Declaration of independence

A TS file declares only one type or interface. The file name is the type name to be exposed for easy retrieval and management.

– Declaration of proximity

When a declaration is not referenced or relied upon externally, it can be used in a location close to where it is used. A typical scenario is the Props and State type declarations of the React component.

– Group by duty

In a project, the types that need to be declared can be broadly divided into two categories: Model, which is related to the interface request, including input and output parameters; The other category is View, related to interface rendering. Therefore, BASED on the independent declaration, I can group the types according to the dimensions of model and View independently of each other.

So how do you apply model data to the View if it’s a separate type declaration? You may need an Adapter to convert types: DTOTypes -> Adapter -> ViewTypes, to perform conversions like mapping strings in an interface to enumerated types.

– Eliminate “hard-wired” connections

Instead of forcing the relationship between two interfaces or types, such as the creation and update of an interface, maybe the fields are the same, but one has an ID and the other doesn’t, so we might want to write a type and then the ID is optional. This saves one type, but may cause other problems. For example, the data with id is passed to the new interface, but ts cannot check it. So, don’t bother splitting it into CreateInputDTO and UpdateInputDTO.

– Finite abstraction

We can abstract out generic declarations on the basis of eliminating “hard-core” associations.

Based on the above principles, solve my problems as a beginner in the type declaration, if there is wrong or better advice, welcome to point out ~

3. All-purpose ointment

Not all type declarations are created equal. As any gives you a different kind of pleasure when reporting a type error that really doesn’t resolve the problem, but it’s not recommended.

How to reference external libraries

Let’s talk about the use of third-party libraries in TS environments.

In JS, NPM has a rich library to help us complete the daily coding, perhaps not all of the library can be fully applied to TS, because some of the lack of type declarations.

For example, using React in TS, you get a type checking error like this:

Because the React library doesn’t have a type declaration.

It is now common for the capability implementation and type implementation to be separated into two libraries where you need to install type declarations: @types/react.

When encountering the above problems, try installing @types/[package].

However, not all libraries have implementation of type declarations, and many do not support TS, but what if you have to use the library?

Write your own statement!

Using Progressbar.js as an example, the basic usage is as follows:

import * as ProgressBar from 'progressbar.js';

new ProgressBar.Circle(this.$progress, {
  strokeWidth: 8.trailColor: '#e5e4e5'.trailWidth: 8.easing: 'easeInOut'
});
Copy the code

The Circle constructor takes two arguments: HTMLElement and options. OK, come on~. The Circle constructor takes two arguments: HTMLElement and options. OK

// First declare the module:
declare module 'progressbar.js' {
  The Circle class is exposed in the module
  export class Circle {
    constructor(container: HTMLElement, options: Options); } // Constructor Options need to be declared separately interface Options {easing? : string; strokeWidth? : number; trailColor? : string; trailWidth? : number; }}Copy the code

This gives us a simple declaration, but of course the actual API in use is more complex than the above, so we can supplement those declarations depending on the usage and which APIS or parameters are used.

How to organize a TS project

In the TS project directory organization, just like in JS project, add the declaration of types.

It is important to expose all types of capabilities that you wish to expose. Unfriendly declarations can be very painful for the people accessing your project. Also, specify the path of type in package.json, such as “types”: “dist/types/index.d.ts”

Also, be sure to add TSLint, which is a more formal way to implement functions with TS, especially for getting started.

TS makes a difference

In terms of the feeling of contact with TS for a month, after the pain of the grinding period, you can gradually feel the convenience brought by TS.

For example, if you remember the name of A type is ABC, you type A in VSCode, and then you find my declaration, press enter, and oh my god, import comes in, you don’t have to type it word by word… /.. /.. /.. /, you don’t need to check whether the directory level is correct.

In addition, strong type is not without benefits ah, wave writing used may still leave hidden trouble, a little constraint or…

Although you have to type more import * as xx from ‘xx’ every day, your code is also more reliable.

With your mutual encouragement, feel the next generation of ES standards in advance, TS use it

Coordinate nanjing Alibaba, looking for a front-end P7, job requirements and benefits with Hangzhou, technology stack React, have Typescript experience is preferred. Interested parties contact: [email protected]

About Fundebug

Fundebug focuses on real-time BUG monitoring for JavaScript, wechat applets, wechat games, Alipay applets, React Native, Node.js and Java online applications. Since its launch on November 11, 2016, Fundebug has handled more than 1 billion error events in total, and paid customers include Google, 360, Kingsoft, Minming.com and many other brands. Welcome to try it for free!