Translation: Crazy geek

Original text: 2 ality.com/2018/04/typ…

What will you learn

After reading this article, you should be able to understand the following code:

interfaceArray<T> { concat(... items:Array<T[] | T>): T[];
  reduce<U>(
    callback: (state: U, element: T, index: number, array: T[]) = > U,
    firstState?: U): U;
  ···
}
Copy the code

If you think this code is mysterious — then I agree with you. But these symbols are relatively easy to learn. Once you understand them, you’ll be able to understand the code completely and accurately without having to read lengthy English instructions.

Running code cases

TypeScript has an online runtime environment. To get the most comprehensive information, you should turn on all Options in the “Options” menu. This is equivalent to running the TypeScript compiler in –strict mode.

Details on type checking

I always like to turn on the –strict switch when working with TypeScript. Without it, your program might be a little easier to write, but you also lose the benefits of static type checking. This setting can now be turned on with the following Settings:

  • --noImplicitAny: If TypeScript cannot infer a type, you must specify it. This is mainly used for arguments to functions and methods: with this setting, you must comment them out.
  • --noImplicitThisIf:thisIf the type is not clear, a prompt message will be displayed.
  • --alwaysStrict: Use JavaScript strict mode whenever possible.
  • --strictNullChecks:nullDoes not belong to any type (except its own type,null), if it is an acceptable value, it must be specified explicitly.
  • --strictFunctionTypes: Tighter checks on function types.
  • --strictPropertyInitialization: If the property value cannot beundefined, then it must be initialized in the constructor.

More information: The compiler Options chapter in the TypeScript manual.

type

In this article, we think of a type as a collection of values. JavaScript language (not TypeScript!) There are 7 types:

  • Undefined: has a unique elementundefinedThe collection.
  • Null: A collection with a unique element “Null”.
  • Boolean: Has two elementsfalsetrueThe collection.
  • Number: a collection of all numbers.
  • String: A collection of all strings.
  • Symbol: A collection of all symbols.
  • Object: A collection of all objects, including functions and arrays.

All of these types are dynamic: they can be used at run time.

TypeScript brings an additional layer to JavaScript: static typing. These exist only when compiling or type-checking source code. Each storage location (variable or attribute) has a static type that predicts its dynamic value. Type checking ensures that these predictions are fulfilled. There are many other things you can do statically (without running code). For example, if the argument x of function f(x) is of static type number, then the function call f(‘ ABC ‘) is illegal because the argument ‘ABC’ is of the wrong static type.

Type annotation

Type comments: The type signature after the colon describes the acceptable value of a variable. For example, code tells TypeScript that the variable “x” can only store numbers:

let x: number;
Copy the code

You may be wondering if using undefined to initialize x violates static typing. TypeScript doesn’t allow this because it doesn’t allow x to be manipulated before assigning a value to it.

Type inference

Even though every storage location in TypeScript has a static type, you don’t always have to specify it explicitly. TypeScript can generally infer its type. For example, if you write this line of code:

let x = 123;
Copy the code

TypeScript then deduces that the static type of X is number.

Type description

What appears after the colon in a type comment is what is called a type expression. These range from simple to complex and are created as follows.

Primitive types are valid type expressions:

  • Static types corresponding to JavaScript dynamic types:

    • undefined, null

    • boolean, number, string

    • symbol

    • object

    • Note: value undefined and type undefined (depending on location)

  • TypeScript specific types:

    • Array(technically not a type in JS)
    • any(Types of all values)
    • And so forth

Note that “undefined as value” and “undefined as type” are both written as undefined. Is interpreted as a value or type, depending on where you use it. The same goes for NULL.

You can create more type expressions by combining primitive types with type operators, a bit like using the operators Union (∪) and intersection (∩) to merge sets.

Here are some of the type operators that TypeScript provides.

An array type

Arrays play two roles in JavaScript (and sometimes a mixture of the two) :

  • List: All elements have the same type. The length of the array varies.
  • Tuple: The length of an array is fixed. Elements are not necessarily of the same type.

Arrays as lists

An array ARR can be represented as a list in two ways, with its elements being numbers:

let arr: number[] = [];
let arr: Array<number> = [];
Copy the code

Typically TypeScript can infer the type of a variable if there is an assignment. In this case, you actually have to solve the type problem for it, because when using an empty array, it can’t determine the type of the element.

We’ll return to Angle bracket notation (Array

) later.

Array as a tuple

If you want to store two-dimensional coordinate points in an array, you can use the array as a tuple. It looks something like this:

let point: [number.number] = [7.5];
Copy the code

In this case, you don’t need type annotations.

Another example is the return value of Object.entries(obj) : an array with a [key, value] pair that describes each property of obj.

> Object.entries({a:1, b:2})
[ [ 'a', 1 ], [ 'b', 2 ] ]
Copy the code

The return type of object.entries () is:

Array<[string, any]>
Copy the code

Function types

Here is an example of a function type:

(num: number) = >string
Copy the code

This type is a function that takes a numeric type parameter and returns a string. An example of using this type (String is a function here) in a type comment:

const func: (num: number) = > string = String;
Copy the code

Again, we don’t typically use type annotations here because TypeScript knows the type of String and can therefore infer the type of func.

The following code is a more practical example:

function stringify123(callback: (num: number) => string) {
  return callback(123);
}
Copy the code

Because we use a function type to describe the callback argument to stringify123(), TypeScript rejects the following function calls.

f(Number);
Copy the code

But it accepts the following function calls:

f(String);
Copy the code

The return type of the function declaration

It is a good practice to comment out all the arguments to a function. You can also specify the return value type (though TypeScript is very good at inferring it) :

function stringify123(callback: (num: number) => string): string {
  const num = 123;
  return callback(num);
}
Copy the code

Special return value typevoid

Void is a special return value type for functions: it tells TypeScript functions to always return undefined (either explicitly or implicitly) :

function f1() :void { return undefined } // OK
function f2() :void {}// OK
function f3() :void { return 'abc' } // error
Copy the code

Optional parameters

The question mark after the identifier indicates that this parameter is optional. Such as:

function stringify123(callback? : (num: number) => string) { const num = 123; if (callback) { return callback(num); // (A) } return String(num); }Copy the code

Running TypeScript in –strict mode only allows you to make function calls on line A if callback is not omitted on advance checking.

Parameter Default Value

TypeScript supports ES6 arguments.

function createPoint(x=0, y=0) {
  return [x, y];
}
Copy the code

Default values make arguments optional. Type annotations can often be omitted because TypeScript can infer types. For example, it can infer that x and y are both of type number.

If you want to add a type comment, you should write:

function createPoint(x:number = 0, y:number = 0) {
  return [x, y];
}
Copy the code

A restful

You can also use ES6 Rest operators for TypeScript parameter definitions. The type of the corresponding argument must be array:

function joinNumbers(. nums:number[]) :string {
    return nums.join(The '-');
}
joinNumbers(1.2.3); / / '1-2-3'
Copy the code

Union

In JavaScript, variables can sometimes be one of several types. To describe these variables, use union types. For example, in the following code, x is of type NULL or number:

let x = null;
x = 123;
Copy the code

X type can be described as a null | number:

let x: null|number = null;
x = 123;
Copy the code

Type s | t the result of the expression is the type of s and t joint in set theory sense (as we saw before, two sets).

Let’s rewrite the function stringify123() : this time we don’t want the callback to be optional. It should always be called. If the caller does not want to pass in a function, null must be explicitly passed. The implementation is as follows.

function stringify123(
  callback: null | ((num: number) => string)) {
  const num = 123;
  if (callback) { // (A)
    return callback(123); // (B)
  }
  return String(num);
}
Copy the code

Note that we have to double-check that the callback is really A function (line A) before making the function call on line B. If not checked, TypeScript reports an error.

Optional andundefined|T

Type for the optional parameters and type of T for undefined | T parameters are very similar. (This is also true for optional attributes.)

The main difference is that you can omit optional arguments:

function f1(x? :number) { }
f1(); // OK
f1(undefined); // OK
f1(123); // OK
Copy the code

But you can ‘t omit the parameters of type, But you can’t omit undefined | t types of parameters:

function f2(x: undefined | number) { }
f2(); // error
f2(undefined); // OK
f2(123); // OK
Copy the code

valuenullundefinedUsually not included in a type

In many programming languages, NULL is part of all types. For example, as long as the parameter type in Java is String, you can pass NULL without Java reporting an error.

In contrast, in TypeScript, undefined and null are handled by separate disjoint types. If you want to make them effective, there must be a type of joint, such as undefined | string and null | string.

object

Like Arrays, objects play two roles in JavaScript (occasionally mixed and/or more dynamic) :

  • Record: A fixed number of properties known at development time. Each attribute can have a different type.
  • Dictionary: Any number of attributes whose names are unknown at development time. All property keys (strings and/or symbols) have the same type, as do property values.

We will ignore object-as-dictionaries in this article. By the way, maps are usually a better choice than dictionaries anyway.

Describe objects-as-records through an interface

Objects-as-records Interface Description Such as:

interface Point {
  x: number;
  y: number;
}
Copy the code

One of the strengths of the TypeScript type system is its structure, not its naming. That is, the interface Point can match all objects of the appropriate structure:

function pointToString(p: Point) {
  return ` (${p.x}.${p.y}) `;
}
pointToString({x: 5, y: 7}); / / '(5, 7)
Copy the code

In contrast, Java’s nominal type system requires classes to implement interfaces.

Optional attribute

If the attribute can be omitted, place a question mark after its name:

interface Person {
  name: string; company? :string;
}
Copy the code

methods

The interface can also contain methods:

interface Point {
  x: number;
  y: number;
  distance(other: Point): number;
}
Copy the code

Type variables and generic types

With static typing, there are two levels:

  • Value exists in theObject level.
  • Type exists inYuan level.

In the same way:

  • Ordinary variables are defined above the object level.
  • Type variableExists above the meta-level. They are variables whose values are types.

Ordinary variables are introduced via const, let, etc. Type variables are introduced through Angle brackets (<>). For example, the following code contains the type variable T, introduced with

.

interface Stack<T> {
  push(x: T): void;
  pop(): T;
}
Copy the code

You can see that the type parameter T appears twice in the body of the Stack. Therefore, the interface can be intuitively understood as follows:

  • StackIs a bunch of values, all of which have a given typeT. Every time you mentionStack“, must writeT. And we’ll see how that works.
  • methods.push()The acceptance type isTThe value of the.
  • methods.pop()Return type isTThe value of the.

If you use Stack, you must specify a type for T. The following code shows a virtual stack whose sole purpose is to match interfaces.

const dummyStack: Stack<number> = {
  push(x: number) {},
  pop() { return 123}};Copy the code

Example: the map

Map is defined in TypeScript. Such as:

const myMap: Map<boolean.string> = new Map([
  [false.'no'],
  [true.'yes']]);Copy the code

The type variable of a function

Functions (and methods) can also introduce type variables:

function id<T> (x: T) :T {
  return x;
}
Copy the code

You can use this feature in the following ways.

id<number> (123);
Copy the code

Type arguments can also be omitted for type inference:

id(123);
Copy the code

Pass type parameter

Functions can pass other type arguments to interfaces, classes, and so on:

function fillArray<T> (len: number, elem: T) {
  return new Array<T>(len).fill(elem);
}
Copy the code

The type variable T appears three times in this code:

  • fillArray<T>: Introduces type variables
  • elem:T: Using a type variable, select it from the parameters.
  • Array<T>Will:TPassed to theArrayConstructor of.

This means that we do not have to explicitly specify the type T of Array

— it is inferred from the parameter elem:

const arr = fillArray(3.The '*');
  // Inferred type: string[]
Copy the code

conclusion

Let’s use what we’ve learned to understand the code we started with:

interfaceArray<T> { concat(... items:Array<T[] | T>): T[];
  reduce<U>(
    callback: (state: U, element: T, index: number, array: T[]) = > U,
    firstState?: U): U;
  ···
}
Copy the code

This is an Array interface whose element type is T that must be filled in whenever this interface is used:

  • methods.concat()There are zero or more parameters (defined by the REST operator). Each of these parameters has a typeT[]|T. In other words, it’s aTType or an array ofTValue.
  • methods.reduce()Introduces its own type variableU.UDenotes that the following entities all have the same type (you do not need to specify it, it is inferred automatically) :
    • Parameter state of callback() (which is a function)
  • statecallback()(This is a function)
  • Result of callback()
  • callback()The return of
  • .reduce()Is an optional parameterfirstState
  • Result of .reduce()
  • .reduce()The return of

Callback also gets an Element parameter of the same type T as the Array element, where index is a number and Array is the value of T.

Further reading

  • Books (free online) : ‘Exploring ES6’
  • “ECMAScript language types” in the ECMAScript specification.
  • “TypeScript Manual” : Very well written and explains the various other types and type operators that TypeScript supports.
  • The complete ECMAScript standard library type definitions are available on GitHub. This is an easy way to practice type notation.

Welcome to pay attention to Beijing Cheng Yideng public number: [Beijing Cheng Yideng], get more front-end dry goods.