One, foreword

Because typescript has not been introduced in the company’s project, and I feel I have been left behind for a long time due to my laziness, my current understanding of TS is limited to the basic functions of type checking, and I have no idea about some advanced usage, so I want to make a summary of TS learning through notes. Be sure to read typescript Documentation in English when studying, because some of the typescript Chinese web pages are out of date.

Second, type annotation

: Used for type annotation

In the following example, we use type annotations for variables, function parameters, and function return values:

let myName: string = "Alice";

function identity(num: number) :number {
  return num;
Copy the code

Data types

1. Primitive type

1.1 String Type (String)

let name: string='xiaoming';
Copy the code

1.2 Number Types

let age: number=10;
Copy the code

1.3 Boolean type (Boolean)

let flag: boolean=false;
Copy the code


The type names String, Number, and Boolean (starting with capital letters) are legal, but refer to some special built-in types that will very rarely appear in your code. Always use string, number, or boolean for types. The type names String, Number, and Boolean (beginning with a capital letter) are legal, but refer to special built-in types that rarely appear in code. For types, always use String, number, or Boolean.

2. Array type

Array<T>, where T represents the element type in the Array.

let arr1: number[] = [1.2.3]; 
let arr2: Array<number> = [4.5.6];
Copy the code

3. Type of a Tuple

The Tuple type is another Array type that knows exactly how many elements it contains and what types it contains at a particular location, and ts will report an error when accessing a crossover element

const tuple: [number.string] = [2022.'hello world']
Copy the code

4.Enum Enum type

4.1 Common Enumeration

enum Gender{
    FEMALE, / / 0
    MALE  / / 1

// Simply use enumerated types
let User = Gender.FEMALE 
console.log(User) // 0 The default output is 0
Copy the code

Note: By default, the first enumeration value is 0, then each subsequent value is incremented by 1.

The number associated with any enumerator can be changed by a specific assignment:

enum Gender{
    FEMALE = 2./ / 2
    MALE  / / 3
Copy the code

What do enumerated types look like when compiled? Let’s look at the following example:

// Enumeration type
enum Gender{

/ / the compiled
var Gender;
(function (Gender) {
    Gender[Gender["FEMALE"] = 0] = "FEMALE";
    Gender[Gender["MALE"] = 1] = "MALE";
})(Gender || (Gender = {}));
Copy the code

Gender[Gender[“FEMALE”] = 0 = “FEMALE” So Gender[0] = “FEMALE”. You can then reverse map using the Gender variable as follows:

enum Gender{

console.log(Gender[0]); // 'FEMALE'
console.log(Gender['FEMALE']); / / 0
console.log(Gender[Gender.FEMALE]); // 'FEMALE' because Gender.FEMALE == 0
Copy the code

4.2 Constant Enumeration

Using const enumeration

const enum Gender {
let genders = Gender.FEMALE;

/ / the compiled
var genders = 0 /* FEMALE */;
Copy the code

Genders are not included in the constant enumeration. The variable genders = 0 is declared below.

5. Any Any type

The any type has a special place in the TypeScript type system. It gives you a “back door” to the type system, and TypeScript turns type checking off. Any is compatible with all types (including itself) in the type system. Therefore, any type can be assigned to it, and it can be assigned to any other type.

let power: any;

// Assign an arbitrary type
power = '123';
power = 123;

// It is also compatible with any type
let num: number;
power = num;
num = power;
Copy the code

6. Null, and undefined

In the type system, JavaScript null and undefined literals can be assigned to variables of any type, just like any variables labeled with type ANY. The following is an example:

// strictNullChecks: false

let num: number;
let str: string;

// These types can be assigned
num = null;
str = undefined;
Copy the code

Note: StrictNullChecks strictNullChecks: tsconfig.json (true); null and undefined cannot be assigned to other types; they can only be assigned to their own type or to any.

7. Never type

Never represents a value that will not occur.

  • A function that never returns a value (e.g., if it contains while(true) {});

    function loop() :never{
    Copy the code
  • A function that always throws an error(for example: function error() {throw new error(‘ error ‘)}, error returns type never);

    function error() :never{ 
        throw new Error('Error reported')}Copy the code


  • In TS, null and undefined are valid values of any type, so they cannot be correctly detected if they are being used incorrectly. Therefore, TS introduced strictNullChecks

  • Due to strictNullChecks, null and undefined can be detected in this mode. So TS needs a new bottom type. So we introduce never.

    Look at an example:

    function foo(x: string | number) {
      if (typeof x === 'string') {
        console.log(x) // x is a string
      } else if (typeof x === 'number') {
        console.log(x)  // x is of type number
        console.log(x) // x is of type never because it never gets here
       StrictNullChecks: the code will not be executed and x cannot be observed}}Copy the code

8. The void type

Void denotes a function that does not return a value

function log(message: string) :void {
  StrictNullChecks :false returns only null and undefined when strictNullChecks:false
  StrictNullChecks :true) returns undefined
  //return null;
  //return undefined;
Copy the code

In strictNullChecks:true, an error will be reported if null is returned and the type “null” cannot be assigned to type “void”.

Void vs. never

Void denotes no type, and never denotes the type of a value that never exists.

When a function returns a null value, it returns a value of type void, but when a function never returns (or always throws an error), it returns a value of type never. Void can be assigned (when strictNullChecking is false), but never cannot be assigned to anything other than never itself.


  • Symbol is the new primitive type that became available after ES2015 and is created through the Symbol constructor
  • The value of Symbol is unique
let sym2 = Symbol("key");
let sym3 = Symbol("key");
console.log(sym2 === sym3) // false, symbols are unique
Copy the code

10. BigInt

  • BigInt is used to safely store and manipulate large integers

    const max = Number.MAX_SAFE_INTEGER;// The maximum number is 2**53-1
    console.log(max + 1 === max + 2); // true because the maximum number overflows
    Copy the code
  • When we use BigInt, we must add the ESNext compilation helper library

  • To use 1n, you need “target”: “ESNext”, otherwise bigInt text is not available if the target is lower than ES2020.

    const max = BigInt(Number.MAX_SAFE_INTEGER);
    console.log(max + 1n === max + 2n); // false
    Copy the code
  • Number and Bigint are incompatible. JS type Number BigInt, TS type Number BigInt

    let foo: number;
    let bar: bigint;
    foo = bar;
    bar = foo;
    Copy the code

11. Wrapper Object

  • JavaScript comes in two types: Primitive data types and Object types.
  • All primitive data types have no properties
  • Primitive data type
    • Boolean value
    • The numerical
    • string
    • null
    • undefined
    • Symbol

As mentioned above, strings are treated as primitive data types rather than object types in JavaScript, but let’s look at the following code.

let name = 'lili'; 
console.log(name.toUpperCase()); // LILI
Copy the code

It is obvious that name has a toUpperCase property. So is that not true? If name is not an object type, why does it have toUpperCase, toLowerCase, etc?

A quick conclusion:

When a primitive data type method is called, JavaScript makes a quick mandatory switch between the primitive data type and the object type

When we try to access the toUpperCase property of Name, JavaScript forces the String value to be converted to an object type via new String(name), which is the Wrapper object.

It inherits all the methods of a string and is used to get references on its properties. Once the property is invoked, the wrapper object is discarded.

let name = (new String('lili')).toUpperCase();
Copy the code

11.1 Wrapping objects for TypeScript type declarations

let isOK: boolean = true; // The compiler passes
let isOK: boolean = Boolean(1) // The compiler passes

Type "Boolean" cannot be assigned to type "Boolean".
// Boolean is a primitive, but Boolean is a wrapper object. If possible, Boolean is preferred.
let isOK: boolean = new Boolean(1); // Failed to compile
Copy the code

The third line of code compiles in error. Why? The value generated by New Boolean() is actually a wrapped object, not a primitive data type. Here we expect isOK to be a primitive data type, so TypeScript will fail to compile.

12. Object Types

After the basic types, the most common types are object types. This refers to any JavaScript value with attributes, almost all of which are attributes! To define an object type, simply list its attributes and their types.

For example, here’s a function that takes a point object:

function printCoord(pt: { x: number; y: number }) {
    console.log("The coordinate's x value is " + pt.x);
    console.log("The coordinate's y value is " + pt.y);
printCoord({ x: 3.y: 7 });
Copy the code

The parameter is annotated above with a type with two attributes (x and y), both of type number.

12.1 Optional Properties

An object type can also specify that some or all of its attributes are optional, followed by?

function printName(obj: { first: string; last? :string }) {
    // ...
// Both OK
printName({ first: "Bob" });
printName({ first: "Alice".last: "Alisson" });
Copy the code

If you access a property that doesn’t exist, you get undefined instead of a runtime error.

function printName(obj: { first: string; last? : string }) {
    console.log(obj.last.toUpperCase());// Error - might crash if 'obj.last' wasn't provided!
    if(obj.last ! = =undefined) {
        console.log(obj.last.toUpperCase()); // OK}}Copy the code

13. Union Types

  • A union type is a type composed of two or more other types and represents a value that could be any one of those types

    function printId(id: number | string) {
        console.log("Your ID is: " + id);
    // OK
    // OK
    // Error
    printId({ myID: 22342 });
    Copy the code
  • When unassigned, only properties and methods that are common to both types can be accessed on the union type

    The following example, joint type is number | string, it not only string using the method of use:

    function printId(id: number | string) {
        console.log(id.toUpperCase()); / / an error
        // Property 'toUpperCase' does not exist on type 'string | number'. Property 'toUpperCase' does not exist on type 'number'.Property 'toUpperCase' does not exist on type 'string | number'. Property 'toUpperCase' does not exist on type 'number'.
    Copy the code

    The solution is to narrow the type by narrow

    function printId(id: number | string) {
        if (typeof id === "string") {
            // In this branch, id is of type 'string'
        } else {
            // Here, id is of type 'number'
            console.log(id); }}Copy the code

14. Literal Types

const someStr = "abc" 
// Equivalent to:
const someStr: "abc"
// someStr is of type "ABC" and its value can only be ABC

/ / in the same way
const foo = 1
// Equivalent to:
const foo: 1
// Foo is of type 1 (not an integer).

// If the typeof operator is used
typeof someStr // 'string'
typeof foo / / 1

/ / to let
let foo = 1 // foo : number
Copy the code

Literal type matching and union types:

type Direction = 'Up' | 'Down' | 'Left' | 'Right'; 
function move(direction: Direction) {
    // ...

move("Up"); / / here can only pass 'Up' | 'Down' | 'Left' | 'Right' one of the four values
Copy the code

14.1 Possible Problems

Define a method requested by the handleRequest interface. Note the method parameter

function handleRequest(url : string, method : "GET" | "POST") {
    // do...
// Define objects
const req = { url: "".method: "GET" };
handleRequest(req.url, req.method);
// Error : Argument of type 'string' is not assignable to parameter of type '"GET" | "POST"'.
Copy the code

Req. method is inferred to be a string, not “GET”. Because the code can be evaluated between the creation of req and the call to handleRequest, handleRequest can assign a new string to req.method, such as “GUESS,” TypeScript considers this code to be faulty.


  • You can change the inference by adding type assertions in either place:
    / / 1
    const req = { url: "".method: "GET" as "GET" };
    / / 2
    handleRequest(req.url, req.method as "GET");
    Copy the code
  • We can use const to convert the entire object to text type
    const req = { url: "".method: "GET" } as const
    Copy the code

15. Type Aliases

The syntax for a type alias is the type keyword

type Point = {
    x: number;
    y: number;

function printCoord(pt: Point) {
  console.log("The coordinate's x value is " + pt.x);
  console.log("The coordinate's y value is " + pt.y);

printCoord({ x: 100.y: 100 });
Copy the code

You can also name union types:

type StrOrNum = string | number;

/ / use
let sample: StrOrNum;
sample = 123;
sample = '123';

// Check the type
sample = true; // Error
Copy the code

4. Type inference

TypeScript can infer (check) the type of a variable based on a few simple rules

1. The type of the variable, inferred from the definition:

let foo = 123; / / foo is' number '
let bar = 'hello'; / / the bar is' string '

foo = bar; // Error: cannot assign 'string' to 'number'
Copy the code

2. Function return type

The return type can be inferred by a return statement, as shown below. The inferred function returns a number

function add(a: number, b: number) {
  return a + b;
Copy the code

3. The assignment

Function parameter types/return values can also be inferred by assignment. As shown below, foo’s type is Adder, which makes foo’s arguments A and b type number.

type Adder = (a: number, b: number) = > number;
let foo: Adder = (a, b) = > a + b;
Copy the code

4. A structured

These simple rules also apply to structured existence (object literals), such as the case where foo’s type is inferred as {a: number, b: number}

const foo = {
  a: 123.b: 456

foo.a = 'hello'; // Error: 'string' cannot be assigned to 'number'
Copy the code

Same with arrays:

const bar = [1.2.3];
bar[0] = 'hello'; // Error: 'string' cannot be assigned to 'number'
Copy the code

5. Deconstruction

const foo = {
  a: 123.b: 456
let { a } = foo;

a = 'hello'; // Error: 'string' cannot be assigned to 'number'
Copy the code

Same with arrays:

const bar = [1.2];
let [a, b] = bar;

a = 'hello'; // Error: 'string' cannot be assigned to 'number'
Copy the code


The noImplicitAny option tells the compiler to issue an error when a variable cannot be inferred (or can only be inferred as an implicit type of any), you can:

  • By explicitly adding:anyType annotation to make it aanyType;
  • Help TypeScript infer types with more correct type annotations.

Type Assertions

Type assertions tell the compiler that we know exactly what type a variable is, without type checking

For example, TypeScript only knows that this will return some type of HTMLElement, but you probably know that your page will always have an HTMLCanvasElement with a given ID:

const myCanvas = 
    // HTMLElement
    document.getElementById("main_canvas") as HTMLCanvasElement;
Copy the code

But some type assertions are rejected by TS, for example:

const x = 'hello' as number
Copy the code

TS will report an error like this:

Conversion of type ‘string’ to type ‘number’ may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to ‘unknown’ first.

Of course, sometimes you can “cheat” TS with any as T, which is also a double assertion

const a = (expr as any) as T;
Copy the code

Refer to the article

  • Understand TypeScript in depth
  • Typescript English documents
  • Learn Notes TypeScript
  • TypeScript any type & type declaration, the wrapper object that needs attention