preface

Today’s morning reading article is shared by ant Financial data front @AOTO

The text begins here

Q: Why did you write this article? What does the passage mean?

A: We are considering to use TS as the development language in SPA application. We need an article that systematically introduces TS itself and its surroundings to demonstrate that it is scientific and reasonable to use TS as the development language in the project, and it is in line with the trend.

What is the TS

TypeScript

TypeScript = Type + Script (standard JS). TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. TypeScript is a type-defined JS superset compiled into pure JS.

Why use TS

Goal: Complex SPA applications with long life cycles (often several years) to improve code maintainability and online runtime quality while maintaining development efficiency.

From the perspective of development efficiency, although we need to write more type definition code, TS can provide intelligent hints and intellisom bugs under VSCode, WebStorm and other IDES. At the same time, some third-party class library frameworks commonly used in our project have TS type declarations. We can also write declaration files for those stable modules that do not have TS type declarations. For example, our front-end KOP framework (currently an ant internal framework, similar to DVA) can improve the overall development efficiency in team collaboration projects.

Look from the maintainability, iterative maintenance over a long period of time there will be a lot of development and maintenance of project members, team members level difference, the software has the characteristics of entropy, long-term iterative maintenance project of maintainability, gradually reduce the problems always, have a strong type constraints and static checking, and intelligent IDE, with the help of can reduce the speed of the software corruption, improve maintainability, Strong typing and static type checking can be a big help when refactoring, and even having type definitions can inadvertently increase the frequency of refactoring (safer and safer).

Look from the online running quality, our SPA project many bugs are now due to some of the caller and the called party (such as the collaboration of the component module, interface or function calls) data format does not match, due to the static checking TS have a compile time, let’s bug, as far as possible in the compiler, plus the IDE intelligent error correction, Bugs can be sensed in advance when coding, and the quality of our online runtimes will be more stable and controllable.

The general research and development process of a complex software is roughly divided into defining problems, requirements analysis, planning and construction, software architecture, detailed design, coding and debugging, unit testing, integration testing, integration, system testing and maintenance. Build activities (mainly coding debugging) account for more than 50% of the workload on medium to large projects. At the same time, in a medium to large project, the proportion of bugs caused by the construction phase accounts for 50% to 75%. For a successful project, construction activities are necessary and more controllable for engineers. 【 code 】

TS scales for large-scale JavaScript applications, as its official tagline JavaScript that Scales says. TS has obvious benefits in terms of teamwork, maintainability, readability, stability (bugs exposed early at compile time), and so on:

The addition of a type system is friendly to both code readers and compilers. For the reader, the type definition, along with the IDE’s smart hints, enhances the legibility of the code; For the compiler, type definitions allow the compiler to catch hidden bugs.

Type system + static analysis check + intellisence/hints make large-scale applications with higher code quality, less bugs at runtime and easier to maintain.

With supporting IDE support such as VSCode, it is convenient to view type inference and reference relationships, which can be more convenient and safe for reconstruction, no longer need to search globally, one by one modification.

Define types for application configuration, application state, front-end and back-end interfaces, and various modules. The entire application is typed one by one, making collaboration more convenient, efficient, and secure.

What can TS do

Static checking

This type of problem is not detected by tools such as ESLint.

Low-level mistakes

const peoples = [{ name: 'tim', age: 20}, { name: 'alex', age: 22}]; const sortedPeoples = peoples.sort((a, b) => a.name.localCompare(b.name));

Copy the code

Error detected when executing TSC:

error TS2339: Property 'localCompare' does not exist on type 'string'.

Copy the code

If you are in an IDE that supports TS (VS Code, WebStorm, etc.), the error message in the localCompare position is very obvious in the IDE without waiting for compilation.

Typing errors like localCompare (or accidentally deleting or adding characters by hand) happen all the time, and if the compiler doesn’t statically check it, it could be a character bloodbath: a hidden runtime bug buried. If this problem takes a long path to discover in a SPA application, it can explode as soon as the user triggers the mine: the application crashes directly (especially in a SPA where there is no page refresh).

Judge not empty

let data = { list: null, success: true}; const value = data.list.length;

Copy the code

Perform TSC compilation:

error TS2532: Object is possibly 'null'.

Copy the code

The data.list.length line directly references the attribute of data.list, but the data format of data.list may not be an array. This scenario often occurs when the front end processes the data returned by the back end interface. That would mean planting a bomb that could detonate at any given moment.

Type inference

const arr = []; arr.toUpperCase(); class Cat { miao() {}}class Dog { wang() {}}const cat = new Cat(); cat.wang();

Copy the code

Perform TSC compilation:

error TS2339: Property 'toUpperCase' does not exist on type 'any[]'.error TS2339: Property 'wang' does not exist on type 'Cat'.

Copy the code

TS has type inference, and calls to the wrong method for different types of execution objects will be detected.

Object-oriented programming enhancements

Access control

class Person { protected name: string; public age: number; constructor(name: string) { this.name = name; }}class Employee extends Person { static someAttr = 1; private department: string; constructor(name: string, department: string) { super(name); this.department = department; }}let howard = new Employee("Howard", "Sales"); console.log(howard.name);

Copy the code

Perform TSC compilation:

error TS2445: Property 'name' is protected and only accessible within class 'Person' and its subclasses.

Copy the code

The name attribute in Person is protected and can only be used in its own class or subclasses. Access control is very useful in object oriented programming, it can help us to do information hiding, a big problem with JS object oriented programming is that there is no native support for information hiding (a lot of times it is done by convention encoding). Information hiding helps to better manage system complexity, which is particularly important in software engineering.

interface

interface Machine { move(): void}interface Human { run(): void}class Base {}class Robot extends Base implements Machine, Human { run() { console.log('run'); } move() { console.log('move'); }}

Copy the code

The Robot class can inherit the Base class and implement Machine and Human interfaces. This combination of inherited classes and implemented interfaces makes object-oriented programming more flexible and extensible.

The generic

class GenericNumber { zeroValue: T; add: (x: T, y: T) => T; }let myGenericNumber = new GenericNumber (); myGenericNumber.zeroValue = 0; myGenericNumber.add = function(x, y) { return x + y; };

Copy the code

GenericNumber defines a template type T that can be passed in built-in or custom types when instantiating the GenericNumber class. Generics (templates) are a common concept in traditional object-oriented programming languages and can be useful in scenarios where code logic is generic and arguments can be dynamically typed.

The type system

interface SystemConfig { attr1: number; attr2: string; func1(): string; }interface ModuleType { data: { attr1? : string, attr2? : number }, visible: boolean}const config: SystemConfig = { attr1: 1, attr2: 'str', func1: () => ''}; const mod: ModuleType = { data: { attr1: '1' }, visible: true};

Copy the code

We define a system configuration type, SystemConfig, and a ModuleType, ModuleType, so we can’t modify config and mod data when using these types. Each called party is responsible for its own external type representation, and the caller only needs to care about the type of the called party, not the internal details. This is the benefit of type constraints, which can be very helpful for team projects with multiple people working together.

Module system enhancement

namespace N { export namespace NN { export function a() { console.log('N.a'); } }}N.NN.a();

Copy the code

TS supports namespaces in addition to ES6’s modular system. This is useful when managing the internals of complex modules.

Cost of using TS

Learning costs

In theory, learning and using a new language can be expensive, but the good news is that TS itself is a superset of JS, which means it can support existing JS code, at least in theory. Learn about type systems and basic object-oriented knowledge, should be able to hold TS, the cost is not very high. Official documents are the best learning material.

Application of the cost

The old project

For older projects, since TS is compatible with the ES specification, it is relatively easy to upgrade existing JS (ES6 and above) code, gradually add type annotations, and gradually improve code robustness. Migration process:

  • NPM installs the typescript package globally and runs TSC –init in the project root to automatically generate the tsconfig.json file.

    The default configuration items are as follows: More configuration items

  • “Target “:” ES5 “: The ES version of the compiled code, with options like ES3, ES2105, etc.

  • “Module “:” CommonJS “: modular organization of compiled code, amd, UMD, ES2015, etc.

  • “Strict “:true: indicates that the check is strict. The check cannot be any or NULL.

  • The tsconfig.json initialization does not need to be modified, adding the “allowJs”: true option.

  • Configure webpack configuration to add TS loaders such as awesome-typescript-loader. (If the project is built based on The Atool-build, it has ts compilation built in, which is omitted.)

loaders: [ // All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'. { test: /\.tsx?$/, loader: "awesome-typescript-loader" } ]

Copy the code
  • Now you can write code named ts and TSX (React). It can coexist with existing ES6 code. VSCode automatically validates this part of the code, and webpack is no problem.

  • As time goes by, we’re looking to refactor old ES6 code into TS code, simply change the file suffix to TS (x), and enjoy the benefits of TS and IDE intellisawareness/error correction.

More migration tutorials: Official Migration Tutorial, Official React Project Migration Tutorial, Community Tutorial 1, Community Tutorial 2.

The new project

For new projects, Microsoft has some great Starter projects that detail how to use TS with other frameworks and libraries. For React projects, see the Starter: typescript-react-starter

The cost comparison

Star means dominant


summary

Can see from the above comparison, using familiar ES as development language only in learning and advantage on cost of pit and the overall amount of code, if only short-term projects that use ES understandable, but our project life cycle lasts several years, iterative upgrade continuously, the TS is comparatively mature community, many learning materials, Moreover, TS brings improved efficiency, maintainability and stability of internal collaborative development, so it is a price worth paying in the long run. Moreover, the existence of various type declaration definition files can improve the development efficiency; In addition, static type checking can reduce the number of bugs and the difficulty of troubleshooting bugs, which also improves efficiency, and makes the whole project relatively more stable and controllable.

Community development

As you can see from Stackoverflow’s 2017 Developer Survey, Google Trends, and NPM download trends, the TypeScript community has grown rapidly, especially in recent years. Especially with the advent of VS Code (written by TS and very TS friendly), the VS Code + TypeScript combination has brought a clean flow of productivity and standardization to the front end. As you can see from Google’s support for TS (Angular versions higher than 2 are written in TS), so are the big international manufacturers.

From the inside of Ant Group, products such as Ant Design and Basement are also based on TS (or at least are in extensive use). Although there are some objections, the overall outlook is positive. With the right soil, it will develop rapidly, such as Ant Design.

The surrounding ecological

Type declaration package

React and various other popular frameworks and libraries have TS declarations. You can install them in your project by using NPM install@types/React. You can search this website for library declarations that you want to install. Once installed, writing code related to those frameworks and libraries will be a great experience, and the function definitions and comments will be automatically prompted, which will improve development efficiency.

IDE

Popular IDES such as VS Code and WebStorm have very friendly support for TS. VS Code is even written by TS itself.

An in-depth look at TS

TS language design objectives

The target

You can do static checking at compile time, provide a structured device for large-scale code, compile custom readable JS code, align it with the ECMAScript standard, use a consistent, removable, structured type system, protect the runtime behavior of compiled JS code, and so on.

The target

Mimic an existing language, optimize the performance of compiled code, apply the “right” type system, add runtime type information, and so on.

TS a brief history of

In recent years, with the V8 platform, the major modern browsers up, JS running platform continues to improve, but, JS for large application development is very difficult, JS language is not designed for large applications, it is a scripting language, it does not have static type verification, but more importantly, He didn’t provide classes, modules/namespaces, interfaces, etc., which are required for large scale applications. He also has GWT and other projects that allow you to develop large JS applications in other languages, such as Java and other object-oriented languages. You can use nice ides like Eclipse, but these projects don’t write code in JS, so if you want to use something in JS, you might have to struggle to implement it in another language. So we thought about how to enhance the JS language. TS is a language for developing large JS applications. More specifically, TS is a typed JS superset that compiles to pure JS. So in general, JS code is also TS code. The TS compiler itself is also written by TS and runs the Node.js environment. [Anders Hejlsberg: Introducing TypeScript 2012]

Here’s a graph from TS’s recent Build conference:


As shown in the figure, the JS of Web and Node platform always has a distance from the latest JS specification, and the distance of Web platform is farther. TS can fill this gap, so that users can use the latest features on both Web and Node platform, use elegant JS, and improve productivity. Anders Hejlsberg: What’s New in TypeScript? 2017

Contrast with Flow and Babel

vs Flow

As you can see from this article, the basic type-checking capabilities are not that different now, but TS beats Flow in terms of surrounding ecology, document integrity, and community resources.

vs Babel

Babel is also a very good ES6 to 5 compilation tool, with good plug-in mechanism and good community development. However, in the JS code compiled by the same code, we can see that the TS compiled code is more consistent with the habit, concise and easy to read (both using Playground tool of the official website). I have maintained TS compiled JS code (TS source lost), feel OK.

Babel:

Babel compilation

TS compiled:

TS to compile

TS basic knowledge and core concepts

The base type

let isDone: boolean = false; let decimal: number = 6; let color: string = "blue"; Let list: number[] = [1, 2, 3]; let list: Array = [1, 2, 3]; // Tuple let x: [string, number] = ["hello", 10]; // enumeration enum Color {Red = 1, Green = 2, Blue = 4}let c: Color = color.green; Anylet notSure: any = 4; anylet notSure: any = 4; Function warnUser(): void {alert("This is my warning message"); }let u: undefined = undefined; let n: null = null; Function error(message: string): never {throw new error(message); }// Let someValue: any = "this is a string"; let strLength: number = ( someValue).length; let strLength: number = (someValue as string).length;

Copy the code

For more information, please refer to the official documentation. Here are some core concepts that are different from ES :).

interface

One of the core tenets of TS is that type checking focuses on the shape of values, sometimes called “duck typing” or “structural subtyping.” In TS interfaces take on such a role, defining shapes and constraints for use internally or in collaboration with external systems. An example:

interface SystemConfig { attr1: string; attr2: number; func1(): string; func2(): void; }

Copy the code

This interface defines the shape of the system configuration, attr1 and attr2, and func1 and func2, so that const systemConfig is defined: SystemConfig = {}, SystemConfig cannot be modified at will, it has a shape.

In Java, we advocate interface programming, which is superior to Effective Java classes. In TS class systems, interfaces can play a similar role. You can implement interfaces with implements, which allow for more flexible inheritance, such as:

class A extends BaseClass implements BaseInterface1, BaseInterface2 {}

Copy the code

Class A inherits BaseClass and BaseInterface1 and BaseInterface2 interfaces.

module/namespace

External modules are written in the same way as ES6 modules. Internal modules are recommended to use namespace, for example:

namespace Module1 { export interface SubModule1 {} export interface SubModule2 {}}const module: Module1.SubModule = {}

Copy the code

Namespaces can also be implemented in JS as object literals, and many JS libraries in the early years have done this, but it is clear that with this explicit namespace declaration, the code is much more readable and cannot be changed at will, unlike it is easily overridden with native JS objects.

Access control

TS has public, protected, and private access privileges similar to those of traditional object-oriented languages, which are useful in large applications and are not expanded here.

other

Classes, decorators, async/await, etc. are written similarly to ES6 and ES7, except that generics are relatively difficult to master.

The Type and the Type System

TypeScript = Type + Script. How do we define Type in programming languages?

In computer science, data types, or simply types, are categories of data that tell the compiler/interpreter what the programmer wants to do with the data. Basic data types such as integers, booleans, and characters, combined data types such as groups, objects, and abstract data types such as queues, stacks, collections, dictionaries, and so on. Data types are used in the type system, which provides the way in which types are defined, implemented, and used. Each programming language has its own type system implementation (if any).

Let’s look at the definition of Type System:

In a programming language, a type system is a collection of rules that assign attributes called types to variables, expressions, functions, modules, and other program building elements in a program. These types specify and force, perhaps implicitly, programmers on how to use data structures. The primary purpose of a type system is to reduce the number of bugs that a program can produce by defining an interface for collaboration between different parts of the program and checking that the different parts collaborate in a consistent way. This check may be static (compile time) or dynamic (run time), or both.

Benefits of the type system

Detect errors

The most obvious benefit of static type checking is that errors can be detected early in the program. Bugs are detected early so they can be fixed quickly, rather than lurking in the code until mid-deployment or even live. Furthermore, errors can be more accurately located at compile time, whereas at run time, the effects of errors may not be easily detected until a problem occurs in the program.

Applications can have a variety of data structures, and if a data type is changed, the front end will often handle this refactoring through a global lookup. Static type checking, on the other hand, allows you to detect all possible errors once you compile again, and the IDE’s intelligent error prompts make refactoring easier and easier.

abstract

Another important way that type systems support the programming phase is by enforcing discipline. In large-scale software systems, type systems form the backbone of component collaboration systems. A type is represented in the interface of a module (or related structure such as a class). An interface can be thought of as a “module type,” which represents the functionality that a module can provide and is a contract between an implementer and a user.

Clear interfaces in large-scale structured software systems with a large number of modules working together can make design more abstract, and the design and discussion of interfaces are independent of their implementation. In general, more abstract thinking about interfaces leads to better designs.

Types make programmers think in a higher dimension, rather than getting bogged down in the details of the underlying computer implementation. For example, we can think of strings as character sets, not just arrays of bits. At a higher level, type systems allow us to think and express collaboration between any subsystem/subroutine in terms of interfaces, and interface definitions allow consistent communication between subsystems/subroutines.

document

Types are also useful for reading programs. Type declarations and module interfaces in the program header form the shape of the document that provides hints for the behavior of the program. Also, unlike what is described in comments, this form of documentation is not out of date because it is validated each time you compile, which is particularly important in module signatures.

In type systems that reuse expressiveness, types can be seen as a way of describing programmer intentions. For example, we declare that a function returns a timestamp, which makes it clear that the function returns an integer type in further code calls.

Language security

The term “safe language” is controversial. Heavily influenced by the language community. Unofficially, a secure language can be defined as programming without the possibility of killing itself from the ground up.

The type system allows the compiler to check for nonsensical or possibly illegal code. For example, we know that 3/’ Hello world’ is illegal, and that strong typing provides more security, but not complete type safety.

The efficiency of

Static type checking provides useful compile-time information. For example, if a type requires four bytes in memory, the compiler might use more efficient machine instructions.

Static type, dynamic type, weak type, strong type

Static typing: The type of each variable is known at compile time. Type error compile failure is a syntax problem. Such as Java, C++.

Dynamic typing: the type is not known at compile time, but at run time. Type errors throw exceptions that occur at run time. Such as JS, Python.

Weak typing: Tolerates implicit type conversions. For example, JS, 1+’1’=’11’, number converted to character.

Strong typing: Implicit type conversions are not tolerated. In Python, 1+’1′ raises TypeError.

Accept the TS

I was a little resistant to TS when it first came out, or I felt similar to it when it was compiled into JS languages such as CoffeeScript and Dart. I felt that IT was the product of other languages’ penetration into JS. In the past year or two, THE voice of TS has become stronger and stronger in the community, and I also started to do large-scale JavaScript applications, and gradually rerecognized TS. I gradually realized the importance of TS type system, TSC static checking, VS Code and other IDE support for developing maintainable and stable large JavaScript applications.

Weigh the

How to make better use of JS dynamic and TS static characteristics, we need to combine the actual situation of the project to make a comprehensive judgment. Some suggestions:

If it’s a small to medium size project with a short life cycle, use JS instead of getting stuck with TS.

For large applications with a long life cycle, you are advised to try TS. Open source projects such as VS Code, GitHub, Slack, Asana, Palantir.

If it is a public module such as a framework or library, then TS is recommended. Examples include Ant Design, Angular, Ionic.

Whether to use TS depends on the actual project size, project life cycle, team size, team members and other actual conditions.

Finally, I recommend:

Issue 1009: New TypeScript 2.4 features

From JavaScript to TypeScript

About this article

Author: @ aoto

Original: https://juejin.cn/post/6844903497205448711