TypeScript basic usage

TypeScript

What is TypeScript

  • JavaScript superset
  • Support ECMAScript6 standard and output ECMAScript 3/5

The difference between JavaScript and TypeScript

TypeScript is a superset of JavaScript and extends the syntax of JavaScript. Therefore, existing JavaScript code can work with TypeScript without any modification. TypeScript provides static type checking at compile time through type annotation

Install typescript

npm install -g typescript

tsc app.ts

Or online typescript compilation website:

TypeScript Playground

Basic data type

  • Boolean type
let bool: boolean = false;
// js
let bool = false;
  • number
let num: number = 6
// js
let num = 6
  • character string
let str: string = 'string'
// js
let str = 'string'
  • array
let list: number[] = [1, 2, 3];
// js
let list = [1, 2, 3];
  • Tuple tuple
let x: [string, number] = ['hello', 6]
// js
let x = ['hello', 6];
  • Enum enum
enum Direction {
    NORTH
    SOUTH
    EAST
    WEST
}

// js
var Direction;
(function (Direction) {
    Direction[Direction["NORTH"] = 0] = "NORTH";
    Direction[Direction["SOUTH"] = 1] = "SOUTH";
    Direction[Direction["EAST"] = 2] = "EAST";
    Direction[Direction["WEST"] = 3] = "WEST";
})(Direction || (Direction = {}));
  • any
let notSure: any = 4;
  • void

Used to identify the type of return value of a method, indicating that the method has no return value.

function hello(): void {
    alert("Hello Runoob");
}
// js
function hello() {
    alert("Hello Runoob");
}
  • null

Indicates that the object value is missing.

let n: null = null;
  • undefined
let u: undefined = undefined;

By default, null and undefined are subtypes of all types. That is, you can assign null and undefined to variables of type number. However, when you specify the -- strictNullChecks tag, null and undefined can only be assigned to void and their respective values.

  • never

Never types represent the types of values that never exist. For example, never type is the return value type of function expressions or arrow function expressions that always throw exceptions or have no return value at all; Variables can also be of type never when they are constrained by type protection that is never true.

// The function returning never must have an unreachable end point
function error(message: string): never {
    throw new Error(message);
}

// The inferred return value type is never
function fail() {
    return error("Something failed");
}

// The function returning never must have an unreachable end point
function infiniteLoop(): never {
    while (true) {
    }
}
  • Object

object represents a non primitive type, that is, a type other than number, string, boolean, symbol, null or undefined.

Using object type, you can better represent objects like An API like create. For example:

declare function create(o: object | null): void;

create({ prop: 0 }); // OK
create(null); // OK

TypeScript assertion

Type assertions take two forms

  1. Angle bracket syntax
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
  1. as syntax
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;

Type guard

Type protection is an expression that performs runtime checks to ensure that the type is within a certain range. In other words, type protection ensures that a string is a string, although its value can also be a numeric value. Type protection is not completely different from feature detection. Its main idea is to try to detect attributes, methods or prototypes to determine how to deal with values. At present, there are four main ways to realize type protection:

  • Attribute judgment: in
interface Foo {
    foo: string;
}

interface Bar {
    bar: string;
}

function test(input: Foo | Bar) {
    if('foo' in input) {
        // Here, the input type "tightening" is Foo
    } else {
        // Here, the input type "tighten" is Bar
    }
}
  • Type judgment: typeof
function test(input: string | number) {
    if(typeof input == 'string') {
        // Here, the input type "tighten" is string
    } else {
        // Here, the input type "tightening" is number
    }
}
  • Instance judgment: instanceof
class Foo {};
class Bar {};

function test(input: Foo | Bar) {
    if(input instanceof Foo) {
        // Here, the input type "tightening" is Foo
    } else {
        // Here, the input type "tighten" is Bar
    }
}
  • Literal equality judgment = =,! =, = =, = ===
type Foo = 'foo' | 'bar' | 'unknown';

function test(input: Foo) {
  if (input != 'unknown') {
    // Here, the input type "tightening" is' foo '|' bar '
  } else {
    // Here, the input type "tightening" is "unknown"
  }
}

Advanced type

1. Union Types

If the code base wants to pass in a number or string type parameter, you can use the union type as the padding parameter:

/**
 * Takes a string and adds "padding" to the left.
 * If 'padding' is a string, then 'padding' is appended to the left side.
 * If 'padding' is a number, then that number of spaces is added to the left side.
 */
function padLeft(value: string, padding: string | number) {
    // ...
}

let indentedString = padLeft("Hello world", true); // errors during compilation

If a value is a union type, we can only access members common to all types of this union type.

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

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

function getSmallPet(): Fish | Bird {
    // ...
}

let pet = getSmallPet();
pet.layEggs(); // okay
pet.swim();    // errors
  • Type protection and differentiation
let pet = getSmallPet();

if ((<Fish>pet).swim) {
    (<Fish>pet).swim();
}
else {
    (<Bird>pet).fly();
}

Type alias

Type aliases are used to give a type a new name.

type Message = string | string[];

let greet = (message: Message) => {
  // ...
};

Cross type

Cross type is to combine multiple types into one type. This allows us to stack existing types together into one type, which contains all the required types of features.

function extend<T, U>(first: T, second: U): T & U {
    let result = <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();

function

Function definition

// Named function
function test() {
}

// Anonymous function
let test = function() {};

Function type

function add(x: number, y: number): number {
    return x + y;
}

let myAdd = function(x: number, y: number): number { return x + y; };

Optional parameters

The compiler will verify that the number of parameters passed to a function must be consistent with the number of parameters expected by the function.

In JavaScript, each parameter is optional and can be passed or not. When no parameter is passed, its value is undefined. In TypeScript, we can use it next to the parameter name? Realize the function of optional parameters.

function test(a: string, b?: string) {
    if(b) {
        return b
    } else {
        return a
    }
}

Optional parameters must follow the required parameters.

Default parameters

function buildName(firstName: string, lastName = "Smith") {
    return firstName + " " + lastName;
}

let result1 = buildName("Bob");                  // works correctly now, returns "Bob Smith"

Remaining parameters

Required parameters, default parameters and optional parameters have one thing in common: they represent a parameter. Sometimes you want to manipulate multiple parameters at the same time, or you don't know how many parameters will be passed in. In JavaScript, you can use arguments to access all the parameters passed in.

function buildName(firstName: string, ...restOfName: string[]) {
  return firstName + " " + restOfName.join(" ");
}

let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");

Ellipsis is also used on function type definitions with remaining parameters:

function buildName(firstName: string, ...restOfName: string[]) {
  return firstName + " " + restOfName.join(" ");
}

let buildNameFun: (fname: string, ...rest: string[]) => string = buildName;

heavy load

array

Data deconstruction

let x: number; let y: number; let z: number;
let five_array = [0,1,2,3,4];
[x,y,z] = five_array;

Array expansion operator

let two_array = [0, 1];
let five_array = [...two_array, 2, 3, 4];

Array traversal

Interface

Interface

interface IQuery {
  page: number;
  findOne(): void;
  findAll(): void;
}

optional attribute

interface SquareConfig {
  color?: string;
  width?: number;
}

Read only attribute

interface Point {
    readonly x: number;
    readonly y: number;
}

Difference between readonly and const

The simplest way to judge whether to use readonly or const is to use it as a variable or as an attribute. Const is used as a variable, and readonly is used as an attribute.

Additional attribute checks

let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig);

perhaps

interface SquareConfig {
    color?: string;
    width?: number;
    [propName: string]: any;
}

Function type

In addition to using interfaces to describe object structures, interfaces can also describe function types.

interface SearchFunc {
  (source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
  let result = source.search(subString);
  return result > -1;
}

generic paradigm

In software engineering, we should not only create consistent and well-defined API s, but also consider reusability. Components can support not only current data types, but also future data types, which provides you with very flexible functions when creating large-scale systems.

function identity<T>(arg: T): T {
    return arg;
}

Mode of use

  • The first is to pass in all parameters, including type parameters
let output = identity<string>("myString");  // type of output will be 'string'
  • The second type inference -- that is, the compiler will automatically help us determine the type of T according to the passed parameters
let output = identity("myString");  // type of output will be 'string'

Generic class

class GenericNumber<T> {
    zeroValue: T;
    add: (x: T, y: T) => T;
}

Generic constraints

interface Lengthwise {
    length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);  // Now we know it has a .length property, so no more error
    return arg;
}

Iterators and generators

Iteratability

When an object implements Symbol.iterator Property, we think it is iterative. Some built-in types such as Array, Map, Set, String, Int32Array, Uint32Array, etc. have implemented their own symbol iterator. Symbol on object The iterator function is responsible for returning values for iteration.

Decorator

Mixins

reference material

Keywords: TypeScript

Added by Sako on Thu, 06 Jan 2022 01:57:09 +0200