TypeSciptIn order to make the code written more standard, more conducive to maintenance, increased the type of verification, so write latertsThe code must specify the type

You don’t specify a type after TypeScript, but you can’t change the type later. Otherwise, an error will be reported, but it won’t prevent the code from compiling because JS is allowed

1. Basic types

1.1 Boolean type (boolean)

let flag: boolean = true;
flag = 123; // An error is reported because it does not match the type
flag = false; Boolean types can only be true and false
Copy the code

1.2 Number Types (number)

let num: number = 123;
console.log(num);
Copy the code

1.3 String Type (string)

let str: string = "string";
console.log(str);
Copy the code

1.4 Array Types (Array)

There are two ways to define arrays in TypeScript

// The first method defines an array
let arr1: number[] = [1.23.]; // An array full of numbers

// The second way to define an array
let arr2: Array<number> = [1.2.3];
Copy the code

1.5 Read-only Array Types (ReadonlyArray)

Properties such as the array members in read-only arrays and the length of the array itself cannot be modified, nor can they be assigned to the original array

let a: number[] = [1.2.3.4];
let ro: ReadonlyArray<number> = a; A read-only array is just a built-in generic interface
ro[1] = 5; / / an error
ro.length = 5; / / an error
a = ro; // Error because ro type is Readonly, the type has changed
a = ro as number[]; // True, cannot be copied by the above method, but can be copied by type assertion
Copy the code

1.6 Tuple Type (tuple)

A tuple type is a type of array. An array can contain only one type, or an error will be reported. A tuple type can contain multiple types

// Tuple type specifies a type for each member of an array
let arr: [number.string] = [123."string"]; // Note that an error is reported if the types do not match
arr[2] = 456; / / an error
// Because tuple types are declared in one-to-one correspondence, there can only be two members
Copy the code

1.7 Enumeration Types (enum)

/* Passed: enum Enum name {Identifier = integer constant, identifier = integer constant,...... Identifier = integer constant}; Define an enumeration type */
enum Color {
  Red = 1,
  Blue = 3,
  Oragne = 5
}

let color: Color = Color.Red; // color is the color enumeration type, and the value is Red in color, which is 1
console.log(color); / / 1
Copy the code

Note:

  • If no identifier is assigned, the value of the identifier defaults to the index value
  • If an identifier is assigned during a period and subsequent identifiers are not assigned, the indexes of subsequent representations are incremented by the preceding values1
  • Identifiers can be enclosed in quotes and remain unaffected
  • You can also get a string identifier by selecting the index value in reverse
enum Color {
  Red,
  Blue = 3."Oragne"
}
let color1: Color = Color.Red;
let color2: Color = Color.Blue;
let color3: Color = Color.Oragne;
let color4: string = Color[0]; // Get the identifier by getting the index
console.log(color1); / / 0
console.log(color2); / / 3
console.log(color3); / / 4
console.log(color4); // red
Copy the code

1.8 Any Type (any)

Data of any type, like JS, can be typed at will

let num:any = 123;
num = "string";
console.log(num); // string
Copy the code

The specific use

// If you want to get DOM nodes in TS, you need to use any type
let oDiv: any = document.getElementsByTagName("div") [0];
oDiv.style.backgroundColor = "red";
// The DOM node should be an object, but TypeScript has no basic type for objects, so you must use any to avoid errors
Copy the code

1.9 undefinedandnulltype

If you use a variable without specifying undefined, an error will be reported. If you use a variable without specifying undefined, an error will not be reported

let flag1: undefined; // Let flag1: undefined = undefined;
console.log(flag); // undefined

let flag2: null = null; // If the value is not specified as null, an error will be reported when printing
console.log(flag2); // null
Copy the code

Specify multiple possible types for variables

let flag: number | undefined; // This method will not give an error when there is no assignment, because it may be undefined
console.log(flag); // undefined
flag = 123;
console.log(flag); // 123 can also be a numeric type

// Multiple types can also be set
let flag1: number | string | null | undefined;
flag1 = 123;
console.log(flag1); / / 123
flag1 = null;
console.log(flag1); // null
flag1 = "string";
console.log(flag1); // string
Copy the code

1.10 voidtype

In TypeScript, void means that there is no type at all. It is usually used to define methods that return no value. Variables can be typed, but void can only be assigned to undefined and null

In TypeScript, the type of a function indicates the type of its return value, and the type of a function void indicates that it has no return value

function run() :void {
    console.log(123);
    // return cannot have a value, otherwise an error is reported
}

function run1() :number {
    console.log(456);
    return 123; // There must be a return value, and the return value is number, otherwise an error is reported
}

function run2() :any {
    console.log(789); // Since any is an arbitrary type, it is possible not to return a value
}
Copy the code

1.11 nevertype

The never type is a subtype of other types (including NULL and undefine) and represents values that never occur, meaning that variables declared as never can only be assigned by never

let a: undefined;
a = undefined;

let b: null;
b = null;

let c: never; // C cannot be thrown with any values, including null and undefiend
c = (() = >{
    throw new Error("error!!"); }) ();// It can be assigned like this

// A function that returns never must have an unreachable end
function error(message: string) :never {
    throw new Error(message);
}
// A function that returns never must have an unreachable end
function infiniteLoop() :never {
    while (true) {}}// The inferred return value type is never
function fail() {
    return error("Something failed");
}
Copy the code

1.12 objecttype

Object represents a non-primitive type, that is, a type other than number, String, Boolean, symbol, NULL, and undefined

let stu: object = {name:"Zhang".age:18};
console.log(stu); // {name: "zhang3 ", age: 18}

/ / can also
let stu: {} = { name: "Zhang".age: 18 };
console.log(stu); // {name: "zhang3 ", age: 18}
Copy the code
declare function create (o: object | null) :void;
// declare is a declaration keyword that can be written to resolve naming conflicts when declaring a variable
create({ prop: 0 }); // OK
create(null); // OK

create(42); / / an error
create("string"); / / an error
create(false); / / an error
create(undefined); / / an error
Copy the code

2. Advanced type

2.1 Cross Types

Cross typing is merging multiple types into one type. This allows us to superimpose existing types into a single type that contains all the required features of the type

function extend<T.U> (first: T, second: U) :T & U {
  let result = <any> {};// T&U (T, U); // T&U (T, U)
  for (let id in first) {
    (<any>result)[id] = (<any>first)[id];
  }
  for (let id in second) {
    if(! result.hasOwnProperty(id)) { (<any>result)[id] = (<any>second)[id]; }}return result;
}

class Person {
  constructor(public name: string){}}interface Loggable {
  log(): void;
}
class ConsoleLogger implements Loggable {
  log() {
    // ...}}var jim = extend(new Person("Jim"), new ConsoleLogger());
var n = jim.name;
jim.log();
Copy the code

2.2 Association Type

Union types are closely related to cross types, but they are completely different in use, as we use them to separate each type parameter with a vertical line

Union types indicate that a value can be one of several types. With a vertical bar (|) separated for each type, so the number | string | Boolean said a value can be a number, a string, or Boolean

function padLeft(value: string, padding: string | number) {
    // ...
}

let indentedString = padLeft("Hello world".true); // errors can only be string or number
Copy the code

If a value is a union type, we can access only the members that are common to all types of that union type

interface Bird {
    fly();
    layEggs();
}

interface Fish {
    swim();
    layEggs();
}

function getSmallPet() :Fish | Bird { // This error is ignored
    // ...
}

let pet = getSmallPet(); // Only one of the Fish and Bird types can be determined because it is not clear which type is returned
pet.layEggs(); // We can call common methods
pet.swim();    // errors, cannot call a method of a type, because in case of a Bird type, it cannot
Copy the code

2.3 Type Protection

Union types are suitable for cases where values can be of different types. But when we want to know for sure if it’s Fish, the common JavaScript way to distinguish between two possible values is to check whether the member exists, but in TypeScript you must use type assertions first

let pet = getSmallPet();

if ((<Fish>pet).swim) {
    (<Fish>pet).swim();
} else {
    (<Bird>pet).fly();
}
Copy the code
2.3.1 User-defined Type Protection
function isFish (pet: Fish | Bird) :pet is Fish {
    return(<Fish>pet).swim ! = =undefined; // Returns a Boolean value, which TypeScript then Narrows down
}
/* pet is Fish. The predicate is of the form parameterName is Type. ParameterName must come from a parameterName */ in the current function signature
Copy the code
// The 'swim' and 'fly' calls are no longer a problem, because pet types are reduced
if (isFish(pet)) {
   pet.swim();
}else {
   pet.fly();
}
Copy the code

TypeScript not only knows that pet is Fish in the if branch, it also knows that it must not be Fish in the else branch, it must be Bird

2.3.2 typeofType of protection
function padLeft (value: string, padding: string | number) {
    if (typeof padding === "number") {
       return Array(padding + 1).join("") + value;
    }
    if (typeof padding === "string") {
       return padding + value;
    }
    throw new Error(`Expected string or number, got '${padding}'. `);
}
Copy the code

Only two forms of these Typeof type protections can be recognized: Typeof V === “typename” and typeof V! “Typename”, “typename” must be “number”, “string”, “Boolean” or “symbol”. But TypeScript doesn’t prevent you from comparing with other strings, and the language doesn’t recognize those expressions as type-protected

2.3.3 instanceofType of protection
interface Padder {
   getPaddingString(): string
}

class SpaceRepeatingPadder implements Padder {
    constructor(private numSpaces: number){}getPaddingString() {
        return Array(this.numSpaces + 1).join(""); }}class StringPadder implements Padder {
    constructor(private value: string){}getPaddingString() {
        return this.value; }}function getRandomPadder() {
    return Math.random() < 0.5 
      ? new SpaceRepeatingPadder(4) 
      : new StringPadder("");
}

/ / type for SpaceRepeatingPadder | StringPadder
let padder: Padder = getRandomPadder();

if (padder instanceof SpaceRepeatingPadder) {
    padder; // Type refined to 'SpaceRepeatingPadder'
}
if (padder instanceof StringPadder) {
    padder; // Type refinement to 'StringPadder'
}
Copy the code

The right side of instanceof is required to be a constructor, which TypeScript refines to:

  • Of this constructorprototypeProperty if its type is notanyif
  • Constructs the union of types returned by the signature
2.3.4 fornullThe type of

Language is compiled directly, if not in vscode can give a to other types of value assignment for undefined or null, but if use the compile time — strictNullChecks tag, will like vscode cannot assignment, and optional parameters and automatically add | can choose attribute Undefined type

Type protection and type assertion

Because null-capable types are implemented through union types, you need to use type protection to remove NULls

function f(sn: string | null) :string {
    if (sn === null) {
        return "default";
    } else {
        returnsn; }}// The following form can also be used
function f(sn: string | null) :string {
    return sn || "default";
}
Copy the code

If the compiler is unable to remove null or undefined, you can do so manually using type assertions. Syntax is added! The suffix: identifier. Remove null and undefined from the identifier type

function broken(name: string | null) :string {
  function postfix(epithet: string) {
    return name.charAt(0) + '. the ' + epithet; // error, 'name' is possibly null
  }
  name = name || "Bob";
  return postfix("great");
}

// The above function will report an error
function fixed(name: string | null) :string {
  function postfix(epithet: string) {
    // The name mandatory assertion is not null or undefined, because it is not known whether name is null in nested functions
    returnname! .charAt(0) + '. the ' + epithet; // ok
  }
  name = name || "Bob"; // It is already clear that the name returned must be a string
  return postfix("great"); // But since it is a nested function, it is not known here
}
/* In nested functions: Because the compiler cannot remove null from nested functions (except for function expressions that are called immediately). Because it cannot keep track of all calls to nested functions, especially if the inner function is the return value of the outer function. If you do not know where the function is called, you do not know the type of name at the time of the call */
Copy the code

2.4 Type Aliases

A type alias gives a type a new name. Type aliases are sometimes similar to interfaces, but can work with primitive values, union types, tuples, and any other type that requires handwriting

An alias does not create a new type, but creates a new name to reference that type

type Name = string; // Create an alias with the type keyword
type NameResolver = () = > string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver) :Name {
    if (typeof n === 'string') {
       return n;
    } else {
       returnn(); }}Copy the code

Like an interface, a type alias can be generic, with type parameters added and passed to the right of the alias declaration

type Container<T> = { value: T };

// We can also use type aliases to refer to ourselves in attributes
type Tree<T> = {
    value: T;
    left: Tree<T>;
    right: Tree<T>;
}

// With cross types, we can create some pretty bizarre types
type LinkedList<T> = T & { next: LinkedList<T> };

interface Person {
    name: string;
}

var people: LinkedList<Person>;
var s = people.name; // note that this is an error in vscode because it is more strict and must be assigned before it is used
var s = people.next.name;
var s = people.next.next.name;
var s = people.next.next.next.name;
Copy the code

Type aliases cannot appear anywhere on the right side of declarations

type Yikes = Array<Yikes>; / / an error
Copy the code

2.5 String argument type

The string literal type allows you to specify fixed values that a string must have. In practice, string literal types work well with union types, type protection, and type aliases. By combining these features, you can implement strings of enumeration-like types

type Easing = "ease-in" | "ease-out" | "ease-in-out";
class UIElement {
    animate(dx: number, dy: number, easing: Easing) {
        if (easing === "ease-in") {
            // ...
        } else if (easing === "ease-out") {}else if (easing === "ease-in-out") {}else {
            // error! should not pass null or undefined.}}}let button = new UIElement();
button.animate(0.0."ease-in");
button.animate(0.0."uneasy"); // error: "uneasy" is not allowed here
// Only one of the three allowed characters can be passed as an argument. Passing other values will generate an error
Copy the code

String literal types can also be used to distinguish function overloading

function createElement(tagName: "img") :HTMLImageElement;
function createElement(tagName: "input") :HTMLInputElement;
// ... more overloads ...
function createElement(tagName: string) :Element {
    // ... code goes here ...
}
Copy the code