TS (6) - type inference, type compatibility, advanced type

2019-11-09:

Learning content: type inference, type compatibility, advanced type


 

 

First, type inference: Where type is how Inferred

  In some it did not specify the type of place, type inference will help provide type. Such as: let x = 3; variable xtype is deduced to digital. This inference occurred during initialization of variables and member parameter values and determine the function return value is set by default. In most cases, type inference is straightforward.

 

  Best general types: such as: let x = [0, 1 , null]; two options: number and null, calculating general type of algorithm will consider all types of candidates, and gives a type compatible with all types of candidate. If you do not find the best common type, then type inference result is an associative array type.

 

Context Type:

  TypeScript type inference may be performed in the opposite direction. This is called "classified according to the context." Categorized according to the context occurs when the position of the type in which the expression of related.

window.onmousedown = function(mouseEvent) {
    console.log(mouseEvent.button);  //<- Error
};

  This example will get a type error, the typescript type checker uses the Window.onmousedownfunction of the right type to infer the type of function expressions. Therefore, we can infer the  mouseEventtype of the parameter. If the function expression is not in the context of the type of location,  mouseEventtype of the parameter is specified as required any, so that will not be the error.

 


 

Second, the type of compatibility:

  Lane TypeScript type compatibility is based on the structural subtype of. Structure type is a type using only the members described manner. It contrasts with just nominal (Nominal) type. (Translator's Note: the name of the type based on the type of system, the data type compatibility or equivalence is determined by explicit statement and / or the name of the type with which systems of different structural types, which is based on the type the composition structure and does not require the explicit declaration.)

  TypeScript type system allows some unable to confirm the safety of operations at compile time. When a system with this type of property, be taken as "not reliable". TypeScript allow this unreliable behavior occurs after careful consideration. Through this article, we will explain what will happen when this situation and its favorable side.

 

  The basic rule TypeScript structured type of system is that if xyou want to be compatible y, it yhas at least xthe same properties.

interface Named {
    name: string;
}

let x: Named;
// y's inferred type is { name: string; location: string; }
let y = { name: 'Alice', location: 'Seattle' };
x = y;

  Here we must check ywhether the assignment to xthe compiler checks xeach property to see if the yalso find the corresponding property. In this example, yit must contain the name nameof stringthe type of members. yTo meet the conditions , and therefore the assignment correctly.

 

  (2) Comparison of two functions:

  If the number and the corresponding types are different, they can not be assigned.

 

  (3) The remaining parameters and optional parameters:

  Comparison function compatibility when the optional parameters and parameters must be interchangeable. There are additional optional argument is not an error on source type, the target type of optional parameters not in the source type in the corresponding parameter is not wrong.

When there is a remaining function parameters, it is seen as an infinite number of optional parameters.

  This type of system is unstable, but from the perspective of the runtime view, optional parameters in general is not mandatory, because for most of the function is equivalent to transfer someundefinded

 

  (4) function overloading:

  For overloaded functions, each source overloaded function must find the corresponding function signatures on the target function. This ensures that the objective function can be called where all the source function can be invoked.

  (5) enumeration:

  Enumeration types compatible with the digital type, and numeric types and enumerated types are compatible. Between different enumeration types are not compatible.

  (6) categories:

  With the object class and an interface similar to the literal, with one exception: there are class type and instance part of the static portion. When comparing two classes of object types, only members of the examples will be compared. Within the scope of static members and constructors are not comparable.

class Animal {
    feet: number;
    constructor(name: string, numFeet: number) { }
}

class Size {
    feet: number;
    constructor(numFeet: number) { }
}

let a: Animal;
let s: Size;

a = s;  // OK
s = a;  // OK

  Private members of a class (private) and protected (protected) members will affect compatibility. When checking compatible class instance, if the target type contains a private member, the source must include this type of private members from the same class. Again, this rule also applies to the type of examination that contains protected member instance. This allows subclasses assigned to the parent class, but can not be assigned to other types of the same class.

 

  (7) Note:

  So far, we have used the "Compatibility", it is not defined in the specification in the language. In TypeScript where there are two compatibility: sub-type and assignment. They differ in that the extended sub-assignment type compatibility, increased the number of rules, and allow anyforth assignments, as well as enumback and forth between an assignment and a corresponding digital value.

  Language use in different parts of the mechanism are among them. In fact, the assignment type compatibility is compatibility to control, even in implementsand extendsstatements are no exception.

 


 

 

Third, the level types:

(1) Type Cross:

  The plurality of types into one type. This allows us to overlay the existing multiple types together into one type, which contains all types of desired characteristics. For example,  Person & Serializable & Loggableat the same time it is  Person and  Serializable and Loggable . That is the object of this type also has three types of members.

  CROSS types meaning: match the values ​​of the type A and type B of the cross, is consistent with the type A, but also with Type B.

  United analogy foregoing type, cross type can be considered two types of intersection. Its meaning to cover all the connotations of the original two sets.

 

(2) protection defined types:

  TypeScript in the  type of protection mechanism to make it a reality. The type of protection that some expressions, they will check to make sure that the type at run time in a scope inside. To define a type of protection, we simply define a function, its return value is a  type predicate :

function isFish(pet: Fish | Bird): pet is Fish {
    return (<Fish>pet).swim !== undefined;
}

  pet is FishIs the type of predicate. Predicate to  parameterName is Typethis form,  parameterNameit must be derived from the current function of a parameter name in the signature.

  Whenever the number of variables to call  isFishupon, TypeScript will be reduced to that specific variable type, as long as this type of primitive type variable is compatible.

 

(3) typeof type of protection:

  * These  typeoftypes of protection * There are only two forms can be identified:  typeof v === "typename"and  typeof v !== "typename""typename"must be  "number""string""boolean"or  "symbol". But TypeScript does not prevent you compare with other strings, do not put those language expressions recognized as a type 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}'.`);
}

 

(4) instanceof type of protection:

  instanceofProtection type is a way to refine the type of the constructor.

  instanceofThe right side is a requirement constructor, TypeScript be refined to:

  1. This constructor  prototypetype attribute, if its type is not  anythe case
  2. Signature structure returned type of joint

In this order.

interface Amphibians {
    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("  ");
}

// 类型为SpaceRepeatingPadder | String Amphibians 
easily amphibians: Amphibians getRandomPadder = ();

if (padder instanceof SpaceRepeatingPadder) {
    padder; // type refinement to 'SpaceRepeatingPadder'
}
if (padder instanceof StringPadder) {
    padder; // type refinement to 'StringPadder' 
}

 

(5) minimize the use :( TypeAliases, multi connector)

  It will play a type alias type a new name. Type alias interfaces and sometimes like, but can act on the original value, union types, tuples and anything else you need to type handwritten.

type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
    if (typeof n === 'string') {
        return n;
    }
    else {
        return n();
    }
}

  Type aliases can be like interfaces; however, there are some nuances.

First, the interface to create a new name can be used in any other place . Type alias does not create a new name - for example, an error message will not be using an alias

Another important difference is the type that can not be an alias  extendsand  implements(he is not  extends, and  implementsother types). Because the  software object should be open for extension, but closed for modification , you should try to use the interface instead of an alias type

 

(6) a string (/ Digital) type literal:

  It allows you to specify a string to be a fixed value. In practice, the type can be a string literal, and the type of protection and the type of alias good fit type joint. By using these features combine, you can achieve a similar string enumerated type.

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

 

(7) discriminated union:

  You can merge a single case types, union types, the type of protection and type to create an alias called  discriminated unions advanced mode, which is also called  tagged union or  algebraic data types . Discriminated union is useful in functional programming . Some languages will automatically identify joint for you; and TypeScript is based on existing JavaScript mode. It has three elements:

  1. Example ordinary single type attribute -  distinctive features .
  2. A type alias contains those types of joint -  the joint .
  3. On this type of property protection.
interface Square {
    kind: "square";
    size: number;
}
interface Rectangle {
    kind: "rectangle";
    width: number;
    height: number;
}
interface Circle {
    kind: "circle";
    radius: number;
}

  Each interface has  kindattributes but with different types of string literal. kindAttribute called  recognizable feature or  label . Other attributes are specific to each interface. Note that, at present there is no link between the various interfaces of.

Repeat the joint property:

function area(s: Shape) {
    switch (s.kind) {
        case "square": return s.size * s.size;
        case "rectangle": return s.height * s.width;
        case "circle": return Math.PI * s.radius ** 2;
    }
}

 

(8) Polymorphism of this type:

  Polymorphic  thistype is represented by a class or interface containing  subtype . This is called  F -bounded polymorphism. It is easy to inherit the performance between the coherent interface

  Since this class uses a  thistype, you can inherit it, the new class can use the direct method before, do not need to make any changes.

 

(9) index type:

  Use index type, the compiler can check using the code name of the dynamic properties.

function pluck<T, K extends keyof T>(o: T, names: K[]): T[K][] {
  return names.map(n => o[n]);
}

interface Person {
    name: string;
    age: number;
}
let person: Person = {
    name: 'Cutting' ,
    age: 35
};
let strings: string[] = pluck(person, ['name']); // ok, string[]

  The compiler will check  namewhether it is  Personan attribute. This embodiment also introduces several new type of operator. First the index type query operators . For any type  the result of  joint public property name on the known. As: keyof TTkeyof TT

  keyof PersonIt is completely with  'name' | 'age'each other to replace. The difference is that if you add additional properties to  Person, for example  address: string, it  keyof Personwill automatically become  'name' | 'age' | 'address'.

  T[K]Index access operator . Here, the type of syntax reflects expression syntax. This means that  person['name']with a type  Person['name'] - was in our case  stringtype. However, as an index, like the type of query, you can use an ordinary contexts  T[K], this is where it's powerful. You just make sure the type of variables  K extends keyof Tto it.

 

(10) Mapping Type:

  TypeScript provide a way to create a new type from the old type -  mapping types . In the mapping type, the new type in the same form to convert the old type in each property. For example, you may have become each property  readonlytype, or optional.

(Follow-up supplement ...)

 

 

 

 

 

 

 

 

 

 

Guess you like

Origin www.cnblogs.com/marvintang1001/p/11828700.html