This is the 7th day of my participation in Gwen Challenge

Prepare reconstruction projects to use ts recently, so I understand some of the most basic knowledge of ts and ts website address is: www.tslang.cn/docs/handbo… All the following codes are from ts official website.

1. Basic types

About 15, respectively: Boolean, number, array, tuple, enumeration, any, VIod, null, undefined, never,Object, type assertion, keyword let

/ / a Boolean
let isDone: boolean = false

/ / 2 Numbers
let isNumber: number = 6

/ / 3 characters
let isName: string = 'ncy'

/** * array * first representation ** / 
 
let list1: number[] = [1.2.3.4]
// Array< element type >
let list2: Array<number> = [1.2.3.4]

// A tuple represents an array of known elements and types. The elements need not be of the same type
let x: [number, string] = [1.'2']


/ / the enumeration
enum Color { Red = 1, Green, Blue }
let c: Color = Color.Green

// Any
let notSure: any = 4
notSure = "1111"
notSure = false

let list: any[] = [1.true."free"];

list[1] = 100;


// Void means that there is no type. When a function has no return value, you usually see a return value of type Void
function warnUser() :void {
  console.log("This is a test")}// Declaring a void variable is useless because you can only assign undefined and null to it:
let unusable: void = undefined;

In TypeScript, Undefined and Null have their own types called Undefined and Null, respectively

// Never represents the types of values that Never exist.
function error(message: string) :never {
  throw new Error(message)
}
function fail() {
  return error('Something failed')}// Object indicates a non-primitive type
declare function create(o: object | null) :void;
create({ prop: 0 });

/** * type assertions * One is the "Angle bracket" syntax: ** / 
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
/ / as syntax
let someValue1: any = '1'
let strLength1: number = (someValue as string).length
Copy the code

2. Variable declarations

Var, let, const and deconstruction, the first three are used a lot. Deconstruction

// var let const destruct
let input = [1.2]
let [first, second] = input

let [first1, ...rest] = [1.2.3]

/ / the default value
function a(b:{c:string,d? :number}) {
  let {c, d = 1 } = b
}
Copy the code

3. The interface

Interface attributes are divided into optional attributes and read-only attributes. Optional attributes have friendly hints and are more flexible in defining data types. Therefore, it is recommended to use them. Define some configuration when comparing read-only properties.

Function type, indexable type, class type, inherited interface, mixed type, interface inherited class and so on 6 kinds

Inheritance interfaces are similar to function inheritance

/** * Optional attributes ** One of the benefits of optional attributes is the ability to pre-define possible attributes, and another is the ability to catch errors when references to non-existent attributes. * If the property is misspelled, you will get an error message * */interface SquareConfig { color? :string; width? :number; [propName: string]: any }function createSquare(config: SquareConfig) :{color:string, area: number} {
  let newSquare = {color: 'white'.area: 100} 
  if(config.color) {
    newSquare.color = config.color
  }
  if(config.width) {
    newSquare.area = config.width * config.width
  }
  return newSquare
}
let squareOptions = {colour: 'red'.width: 100}
// let mySquare = createSquare({color: 'black', opacity: 0.5, width: 100} as SquareConfig)
let mySquare = createSquare(squareOptions)

/** * Read-only attribute ** */ 
 interface Point {
  readonly x: number;
  readonly y: number;
}
let p1: Point = {x: 10.y: 20}
p1.x = 5 // "x" cannot be assigned because it is read-only. ts(2540)

let a: number[] = [1.2.3.4]
let ro: ReadonlyArray<number> = a
ro[0] = 12
ro.push(5)
ro.length = 100
a = ro
// Can be overridden with type assertion:
a = ro as number[]

Copy the code
// Function type
interface SearchFunc {
  (source: string,subString: string): boolean
}
let mySearch: SearchFunc;
mySearch = function(src: string,sub: string) {
  let result = src.search(sub)
  return result > -1
}

/** * indexable type ** / 
interface StringArray {
  [index: number]: string
}

let myArray: StringArray
myArray = ["Bob"."Fred".""]
let myStr:string = myArray[0]

class Animal {
  name: string
}
class Dog extends Animal {
  breed: string
}
interface NotOkay {
  [x: string]: Dog,
}


/ / class type
interface ClockInterface {
  currentTime: Date;
  setTime(d: Date);
}
class Clock implements ClockInterface {
  currentTime: Date;
  setTime(d: Date) {
    this.currentTime = d;
  }
  constructor(h:number, m:number){}}// The difference between class static parts and instance parts
interface ClockConstructor {
  new (hour: number, minute: number): ClockInterface
}
interface ClockInterface {
  tick()
}
function createClock(ctor: ClockConstructor, hour: number, minute: number) :ClockInterface {
  return new ctor(hour, minute)
}
class DigitalClock implements ClockInterface {
  constructor(h:number, m: number){}
  tick(){
    console.log('beep beep')}}class AnalogClock implements ClockInterface {
  constructor(h:number, m: number){}
  tick(){
    console.log('beep beep')}}let digital = createClock(DigitalClock, 12.17);
let analog = createClock(AnalogClock, 7.32);


// Inherit the interface
interface Shape {
  color: string;
}
interface PenStroke {
  penWidth: number;
}
interface Square extends Shape, PenStroke {
  sideLength: number;
}
let square = <Square> {}
square.color = 'black'
square.sideLength = 100
square.penWidth = 50

// Mixed type
interface Counter {
  (start: number): string;
  interval: number;
  reset(): void;
}

function getCounter() :Counter {
  let counter = <Counter>function (start: number) {}
  counter.interval = 123
  counter.reset = function(){}
  return counter
}

let c = getCounter()
c(10)
c.reset()
c.interval = 5.0

// Interface inherits classes
class Control {
  private state: any;
}

interface SelectableControl extends Control {
  select(): void;
}

class Button extends Control implements SelectableControl {
  select(){}}class TextBox extends Control {
  select(){}}class Image implements SelectableControl {
  select(){}}class Location {}
Copy the code

Class 4.

There are inheritance, public, private, and protected modifiers, Readonly modifiers, accessors, static properties, and abstract classes.

** Inheritance is mainly the inheritance of superclasses (base classes) and subclasses (derived classes). If there are functions in the superclass, the subclass needs to have super(), which performs the constructor of the base class. 六四屠杀

/ / inheritance
class Animal {
  move(distanceInMeters: number = 0) {
      console.log(`Animal moved ${distanceInMeters}m.`); }}class Dog extends Animal {
  bark() {
      console.log('Woof! Woof! '); }}const dog = new Dog();
dog.bark();
dog.move(10);
dog.bark();

class Animal {
  name: string;
  constructor(theName: string) { this.name = theName; }
  move(distanceInMeters: number = 0) {
    console.log(`The ${this.name} moved ${distanceInMeters}m`)}}class Snake extends Animal {
  constructor(name: string) {super(name); }
  move(distanceInMeters: number = 5) {
    console.log('Slithering... ')
    super.move(distanceInMeters)
  }
}

class Horse extends Animal {
  constructor(name: string) {super(name)}
  move(distanceInMeters = 45) {
    console.log('Galloping');
    super.move(distanceInMeters)
  }
}

let sam = new Snake('Sammy the Python')
let tom: Animal = new Horse('Tommy the Palomino')
sam.move();
tom.move(34);
Copy the code

Public, private, and protected modifiers

Properties are generally public by default; if set to private, they can only be accessed in the class they declare. At the same time, when comparing, it doesn’t matter where they come from, if all the members’ types are compatible, they are considered compatible.

Protected modifiers behave much like private modifiers, with one difference: protected members are still accessible in derived classes

class Animal {
  private name: string;
  constructor(theName: string) { this.name = theName; }}class Rhino extends Animal {
  constructor() {super('Rhino')}}class Employee {
  private name: string
  constructor(theName: string) {this.name = theName}
}

let animal = new Animal('Goat')
let rhino = new Rhino()
let employee = new Employee('Bob')

animal = rhino
animal = employee // error: Animal is incompatible with Employee.

class Person {
  protected name: string;
  constructor(name: string) {this.name = name}
}

class Employee extends Person {
  private department: string;
  constructor(name: string, department: string) {
    super(name)
    this.department = department
  }
  public getElevatorPitch() {
    return `Hello, my name is The ${this.name} and I work in The ${this.department}. `}}let howard = new Employee('howard'."Sales")
console.log(howard.getElevatorPitch())
console.log(howard.name) // Attribute "name" is protected and can only be accessed in class "Person" and its subclasses. ts(2445)



class Person {
  protected name: string;
  protected constructor(theName: string) { this.name = theName; }}// Employee can inherit Person
class Employee extends Person {
  private department: string;

  constructor(name: string, department: string) {
      super(name);
      this.department = department;
  }

  public getElevatorPitch() {
      return `Hello, my name is The ${this.name} and I work in The ${this.department}. `; }}let howard = new Employee("Howard"."Sales");
let john = new Person("John"); // Error: the constructor for 'Person' is protected.
Copy the code

Readonly modifier, readable only

class Octopus {
  readonly name: string;
  readonly numberOfLegs: number = 8;
  constructor (theName: string) {
    console.log(theName)
      this.name = theName; }}let dad = new Octopus("Man with the 8 strong legs");
dad.name = "Man with the 3-piece suit"; / / error! Name is read-only.
Copy the code

accessor

class Employee {
  fullName: string;
}

let employee = new Employee();
employee.fullName = "Bob Smith";
if(employee.fullName) {
  console.log(employee.fullName)
}

let passcode = 'secret passcode'
class Employee {
  private _fullName: string;
  get fullName() :string {
    return this._fullName
  }

  set fullName(newName: string) {
    if (passcode && passcode === 'secret passcode') {
      this._fullName = newName;
    } else {
      console.log('Error: Unauthorized update of employee! ')}}}let employee = new Employee()
employee.fullName = 'Bob Smith'
if (employee.fullName) {
  alert(employee.fullName)
}
Copy the code

Static properties, note the static properties of grid.origin. X

class Grid {
  static origin = {x: 0.y: 0};
  calculateDistanceFromOrigin(point: {x: number; y: number; }) {
      let xDist = (point.x - Grid.origin.x);
      let yDist = (point.y - Grid.origin.y);
      return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
  }
  constructor (public scale: number) {}}let grid1 = new Grid(1.0);  // 1x scale
let grid2 = new Grid(5.0);  // 5x scale

console.log(grid1.calculateDistanceFromOrigin({x: 10.y: 10}));
console.log(grid2.calculateDistanceFromOrigin({x: 10.y: 10}));

Copy the code

An abstract class

Abstract classes are used as base classes for other derived classes. They are generally not instantiated directly. Unlike interfaces, abstract classes can contain implementation details of members. The abstract keyword is used to define abstract classes and abstract methods within abstract classes.

abstract class Animal {
  abstract makeSound(): void;
  move(): void {
      console.log('roaming the earch... '); }}Copy the code

5. The function

Mainly function parameter definition, residual parameter and this and arrow function

The full function type, preceded by the => symbol before the function and return value type, and void if there is no return value

let myAdd: (baseValue: number, increment: number) = > number = function(x: number, y: number) :number { return x + y; };
Copy the code

Type inference: TS automatically identifies the type when one side specifies the type and the other side does not

// The parameters `x` and `y` have the type number
let myAdd: (baseValue: number, increment: number) = > number =
    function(x, y) { return x + y; };
Copy the code

Optional parameters and default parameters. Optional parameters allow us to pass values without unnecessary values. Optional parameters need to come after required parameters. Default parameters and optional types have similar effects.

function buildName(firstName: string, lastName? : string) {
    if (lastName)
        return firstName + "" + lastName;
    else
        return firstName;
}

let result1 = buildName("Bob");  // works correctly now
let result2 = buildName("Bob"."Adams"."Sr.");  // error, too many parameters
let result3 = buildName("Bob"."Adams");  // ah, just right
Copy the code

The default parameters

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

let result1 = buildName("Bob");                  // works correctly now, returns "Bob Smith"
let result2 = buildName("Bob".undefined);       // still works, also returns "Bob Smith"
let result3 = buildName("Bob"."Adams"."Sr.");  // error, too many parameters
let result4 = buildName("Bob"."Adams");         // ah, just right
Copy the code

Remaining parameters The remaining parameters, that is, you can only take part of the parameters during the parameter appending process, and the remaining parameters are in another array

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

let employeeName = buildName("Joseph"."Samuel"."Lucas"."MacKinzie");
/ / or
function buildName(firstName: string, ... restOfName: string[]) {
  return firstName + "" + restOfName.join("");
}

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

This, generally we need to give a display argument

function f(this: void) {
    // make sure `this` is unusable in this standalone function
}
Copy the code

Function overloading

let suits = ["hearts"."spades"."clubs"."diamonds"];

function pickCard(x: {suit: string; card: number; } []) :number;
function pickCard(x: number) :{suit: string; card: number; };
function pickCard(x) :any {
    // Check to see if we're working with an object/array
    // if so, they gave us the deck and we'll pick the card
    if (typeof x == "object") {
        let pickedCard = Math.floor(Math.random() * x.length);
        return pickedCard;
    }
    // Otherwise just let them pick the card
    else if (typeof x == "number") {
        let pickedSuit = Math.floor(x / 13);
        return { suit: suits[pickedSuit], card: x % 13}; }}let myDeck = [{ suit: "diamonds".card: 2 }, { suit: "spades".card: 10 }, { suit: "hearts".card: 4 }];
let pickedCard1 = myDeck[pickCard(myDeck)];
alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);

let pickedCard2 = pickCard(15);
alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);
Copy the code

6. The generic

The concept of generics: what it does is increase reusability and support multiple types for a component. The essential value is save trouble in my opinion!!

1. The basic

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

Copy the code

There are two ways to use it

First: pass all arguments, including type arguments:

let output = identity<string>("myString")
Copy the code

The second takes advantage of type corollaries — that is, the compiler automatically helps us determine the type of T based on the parameters passed in

let output = identity("myString");
Copy the code

2. Use generic variables

function loggingIdentity<T> (arg:T) :T {
  console.log(arg.length) // Attribute "length" does not exist on type "T".
  return arg
}
Copy the code
function loggingIdentity<T> (arg:T[]) :T[] {
  console.log(arg.length) // Attribute "length" does not exist on type "T".
  return arg
}
Copy the code

The difference is that we add [], which is an array of element type T and returns an array of type T. We use the generic variable T as part of the type to increase flexibility.

Such as:

function loggingIdentity<T> (arg: Array<T>) :Array<T> {
    console.log(arg.length);  // Array has a .length, so no more error
    return arg;
}
Copy the code

Generic types

I understand that this is the specification of functions, such as your pass and return values, etc

function identity<T> (arg:T) :T { return arg }
let myIdentity: <T>(arg:T) = > T = identity
Copy the code

For example, as written above, function of type T, parameter of type T, return of type T, etc., assigned to myIdentity, its type T, can be passed to it as parameter T, return as parameter T. And the generic parameter name can be changed to anything, A,B,C, or D, as long as the number and usage of the same. The following

function identity<T> (arg:T) :T { return arg }
let myIdentity:<U>(arg:U) = > U = identity
Copy the code

You can also define generic functions using literals

function identity<T> (arg:T) :T {return arg}
let myIdentity:{<U>(arg:U): U } = identity
Copy the code

The literal approach allows us to define the interface to generics as follows

interface GemericIdentityFn {
  <T>(arg:T): T
}

function identity<T> (arg:T) :T {return arg}
let myIdentity:GemericIdentityFn = identity
Copy the code

The interface to the whole function is defined directly. And this kind of

interface GemericIdentityFn<T> {
  (arg:T): T
}

function identity<T> (arg:T) :T {return arg}
let myIdentity:GemericIdentityFn<number> = identity

Copy the code

The overall difference is small, but the second advantage is that you can specify generic types.

4. A generic class

class GenericNumber<T> {
  zeroValue: T;
  add:(x:T, y:T) = > T
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = (x, y) = > {return x + y}
Copy the code

We define the generics of the class. When we create a new object, we can perform the generics of the class, currently number, so we change the specified type to string. The following

class GenericNumber<T> {
  zeroValue: T;
  add:(x:T, y:T) = > T
}
let stringNumeric = new GenericNumber<string>();
stringNumeric.zeroValue = ' '
stringNumeric.add = (x, y) = > {return x + y}
console.log(stringNumeric.add(stringNumeric.zeroValue, "test"))
Copy the code

5. Constraints on generics

interface Lengthwise {
  length: number;
}
function loggingIdentity<T extends Lengthwise> (arg:T) :T { 
  console.log(arg.length)
  return arg
}
Copy the code

T inherits Lengthwise, all our arguments must contain length and be of type number

Behind there are two examples, I do not quite understand, understand can give directions, thank you!!

Use type parameters in generic constraints

function getProperty(obj: T, key: K) {
    return obj[key];
}
let x = { a: 1.b: 2.c: 3.d: 4 };
getProperty(x, "a")
getProperty(x, "m")
Copy the code

Use class types in generics

When TypeScript uses generics to create factory functions, you need to reference the class type of the constructor

function create<T> (c: {new(): T; }) :T {
    return new c();
}
Copy the code

Use stereotype attributes to infer and constrain the relationship of constructors to class instances.

class BeeKeeper {
    hasMask: boolean;
}

class ZooKeeper {
    nametag: string;
}

class Animal {
    numLegs: number;
}

class Bee extends Animal {
    keeper: BeeKeeper;
}

class Lion extends Animal {
    keeper: ZooKeeper;
}

function createInstance<A extends Animal> (c: new () => A) :A {
    return new c();
}

createInstance(Lion).keeper.nametag;  // typechecks!
createInstance(Bee).keeper.hasMask;   // typechecks!
Copy the code

7. The enumeration

Using enumerations we can define constants with names. Use enumerations to clearly express intent or to create a differentiated set of use cases. TypeScript supports numeric and string-based enumerations.

1. Enumeration of numbers

enum Direction {
    Up = 1,
    Down,
    Left,
    Right
}
Copy the code

Numeric enumerations have the behavior of incrementing values, but each value is different, and after the first value is initially defined, the rest increments.

2. Enumeration of strings

No increment behavior, but readable value

enum Direction {
    Up = "UP",
    Down = "DOWN",
    Left = "LEFT",
    Right = "RIGHT",}Copy the code

3. Computed and constant members

An enumerator is given the value 0 if it is the first member of the enumeration and has no initializer. If it is a numeric constant, the members are incremented.

enum E1 { X, Y, Z }

enum E2 {
    A = 1, B, C
}

enum FileAccess {
    // constant members
    None,
    Read    = 1 << 1,
    Write   = 1 << 2,
    ReadWrite  = Read | Write,
    // computed member
    G = "123".length
}
Copy the code

4. Join enumerations with the types of enumerators

A subset of non-computed constant enumerators: literal enumerators

A literal enumerator is a constant enumerator that has no initial value, or whose value is initialized to

  1. Any string literal (e.g. “foo”, “bar”, “baz”)
  2. Any numeric literal (e.g., 1, 100)
  3. Numeric literals with unary – symbols applied (e.g. -1, -100)

And you can catch some comparison errors through union enumerations

enum ShapeKind {
    Circle,
    Square,
}

interface Circle {
    kind: ShapeKind.Circle;
    radius: number;
}

interface Square {
    kind: ShapeKind.Square;
    sideLength: number;
}

let c: Circle = {
    kind: ShapeKind.Square,
    // ~~~~~~~~~~~~~~~~ Error!
    radius: 100,
}

enum E {
    Foo,
    Bar,
}

function f(x: E) {
    if(x ! == E.Foo || x ! == E.Bar) {/ / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
        // Error! Operator '! ==' cannot be applied to types 'E.Foo' and 'E.Bar'.}}Copy the code

5. Runtime enumeration

Will be the default number

enum E {
    X, Y, Z
}
function f(obj: { X: number }) {
    return obj.X;
}

// Works, since 'E' has a property named 'X' which is a number.
f(E);
Copy the code