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.--noImplicitThis
If:this
If the type is not clear, a prompt message will be displayed.--alwaysStrict
: Use JavaScript strict mode whenever possible.--strictNullChecks
:null
Does 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 element
undefined
The collection. - Null: A collection with a unique element “Null”.
- Boolean: Has two elements
false
和true
The 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
valuenull
和 undefined
Usually 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:
Stack
Is 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 isT
The value of the. - methods
.pop()
Return type isT
The 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 variableselem:T
: Using a type variable, select it from the parameters.Array<T>
Will:T
Passed to theArray
Constructor 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 aT
Type or an array ofT
Value. - methods
.reduce()
Introduces its own type variableU
.U
Denotes that the following entities all have the same type (you do not need to specify it, it is inferred automatically) :- Parameter
state
ofcallback()
(which is a function)
- Parameter
state
是callback()
(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.