TS: The mystery of the interface

TS: The mystery of the interface

1. Interface basic syntax

interface Person{
    
    
    name : string
}

function sayhelloto(person : Person){
    
    
    console.log('hello,' + person.name);
}

let x = {
    
    
    name : 'yivi',
    age : 20
}
sayhelloto(x);	// hello,yivi

The type checker will not check the order of the attributes, as long as the corresponding attributes exist and the types are corresponding, they can be recognized.

2. Optional attributes

  • Sometimes, some attributes in the interface are not necessary. It just needs to exist in some cases. Interfaces with optional attributes only need to add one after the optional attributes ?.
interface Person {
    
    
    name : string;
    age : number;
    phone? : number     
}

3. Read-only attributes

  • Some object properties can only be modified when the object is just created, and readonlyread-only properties can be specified by adding them in front of the property name .
interface Point {
    
    
    readonly x : number;
    readonly y : number;
}

let p : Point = {
    
     x : 5, y : 5};
p.x = 190;	// error,只能读不能赋值
  • There is a ReadonlyArray<T>type in ts , which is Array<T>similar, except that the method that can modify the array is removed, so it can ensure that the array is not modified after it is created:
let a: number[] = [1,2,3,4];
let b: ReadonlyArray<number> = a;
b[0] = 2;	// error
b.push(4); 	// error
h.length = 20;	//error
a = b;	//error
//正确做法
a = b as number[];
  • If used as a variable, use const
  • If used as an attribute, use readonly

4. Additional attribute checks

  • In the previous example, we passed in an attribute that is not in the interface, and the result is that this additional attribute is ignored; but in an interface with optional attributes, this will fail, indicating that the additional attribute is not expected. To bypass this check, use type assertions.

    interface SquareConfig {
          
          
        color?: string;
        width?: number;
    }
    
    function createSquare(config: SquareConfig): {
          
           color: string; area: number } {
          
          
        // ...
    }
    
    let mySquare = createSquare({
          
           colour: "red", width: 100 } as SquareConfig);
    
  • But the best way is to add a string index signature to the interface.

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

5. Function Type

  • In addition to describing ordinary objects with attributes, interfaces can also describe function types; when defining a function, you need to define a call signature, which is a function definition with only a parameter list and return value type.

    interface searchFunc {
          
          
        (source : string, subString: string) : boolean;
    }
    
    let mysearch : searchFunc;
    mysearch = function (source : string,subString : string) {
          
          
        let result = source.search(subString);
        return result > -1;
    }
    
  • For function types, the parameter names of the function do not need to be consistent with those in the interface. The parameters of the function are checked one by one, and the parameter types at the corresponding positions are required to be compatible. If you don't specify the type, TypeScript will infer the parameter type. If the return value type of the function is different from that of the interface, the type checker will warn us.

    mysearch = function(src : string,sub : string) : boolean {
          
          
        let result = src.search(sub);
        return result > -1;
    }
    
    // or
    
    mysearch = function(src , sub){
          
          
        let result = src.search(sub);
        return result > -1;
    }
    

6. Indexable types

  • The indexable type has an index signature, which describes the type of object index and the corresponding index return value type.

    interface StringArray{
          
          
        [index : number] : string;
    }
    
    let myarr : StringArray;
    myarr = ["yivi","huang"];
    
    let mystr : string = myarr[0];
    
  • TypeScript supports two types of index signatures: string and number. Both types of indexes can be used at the same time, but the return value of a numeric index must be a subtype of the return value type of a string index. This is because when using numberthe time to index, JavaScript will convert it to stringthen go to the index object. That is to say, using 100(one number) to index is equivalent to using "100"(one string) to index, so the two need to be consistent.

    class Animal {
          
          
        name: string;
    }
    class Dog extends Animal {
          
          
        breed: string;
    }
    
    // 错误:使用数值型的字符串索引,可能会以字符串进行索引,有时会得到完全不同的Animal!
    interface NotOkay {
          
          
        [x: number]: Animal;
        [x: string]: Dog;
    }
    
  • String index signatures can describe dictionarypatterns well, and they will also ensure that all attributes match their return value types.

  • Because the string index is declared obj.propertyand obj["property"]the two forms can be.

    interface NumberDictionary{
          
          
        [index: string] : number;
        length : number;	// ok,返回值与索引返回类型一致
        name : string;		// error,string与索引返回类型不一致
    }
    
  • At the same time, it can also be said that the index type is set to read-only.

7. Class

  • Like Java, TypeScript can also use interfaces to enforce properties or methods that a class must implement.

    interface clockInterface{
          
          
        currentTime : Date;
        setTime(d : Date);
    }
    
    class Clock implements clockInterface{
          
          
        currentTime : Date;
        setTime(d : Date){
          
          
            this.currentTime = d;
        }
        constructor(h : number,m : number){
          
          }
    }
    
  • There are two types of classes: static part type and instance type .

  • When using the constructor signature to define an interface and define a class to implement it, an error will be reported.

  • Because when a class implements an interface, only its instance part is type checked. The constructor exists in the static part of the class, so it is not in the scope of inspection.

    // 以下定义会报错
    // Class 'Clock' incorrectly implements interface 'ClockConstructor'.   Type 'Clock' provides no match for the signature 'new (hour: number, minute: number): any'.
    interface ClockConstructor {
          
          
        new (hour: number,minute : number);	// 静态类型
    }
    
    class Clock implements ClockConstructor{
          
          
        currentTime : Date;
        constructor(h: number,m:number);
    }
    
    // 正确示范
    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);	// 返回类型为ClockInterface
    }
    
    class DigitalClock implements ClockInterface {
          
          
        constructor(h: number, m: number) {
          
           }
        tick() {
          
          
            console.log("beep beep");
        }
    }
    
    let digital = createClock(DigitalClock, 12, 17);
    
  • Because createClockthe first parameter is the ClockConstructortype, in createClock(DigitalClock, 12, 17)it, it will check DigitalClockwhether it conforms to the constructor signature.

8. Inherited Interface

  • Like Java, TypeScript also supports interface inheritance;
  • One interface can inherit multiple interfaces;

9. Mixed types

  • The advantage of typescript is that it is flexible and dynamic. An object can be used as a function and an object at the same time, and it has additional attributes.

    interface Counter{
          
          
        (start : number) : string;
    	interval : number;
    	reset : void;
    }
    
    function getCounter() : Counter{
          
          
        let counter = <Counter>function (start : number){
          
          };
        counter.interval = 100;
        counter.reset = function(){
          
          };
        return counter;
    }
    
    let c = getCounter();
    c(10);
    c.reset();
    c.interval = 20;
    

10. Interface Inheritance Class

  • When an interface inherits a class, it will inherit the members of the class but not its implementation. It means that when you create a class inherited by an interface that has private or protected variables, this interface can only be implemented by this class or its subclasses.

    class Control {
          
          
        private state: any;
    }
    
    interface SelectableControl extends Control {
          
          
        select(): void;	
    }
    
    class Button extends Control implements SelectableControl {
          
          
        select() {
          
           }	// ok,因为state为私有成员,所以只有子类才能实现SelectableControl接口
    }
    
    class TextBox extends Control {
          
          
        select() {
          
           }	
    }
    
    // 错误:“Image”类型缺少“state”属性。
    class Image implements SelectableControl {
          
          
        select() {
          
           }
    }
    
    
  • Inside the Controlclass, it is allowed SelectableControlto access private members through the instance state. In fact, the SelectableControlinterface and selectthe Controlclass with methods are the same.

Guess you like

Origin blog.csdn.net/yivisir/article/details/109552136