TS: El misterio de la interfaz

TS: El misterio de la interfaz

1. Sintaxis básica de la interfaz

interface Person{
    
    
    name : string
}

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

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

El verificador de tipos no verificará el orden de los atributos, siempre que existan los atributos correspondientes y los tipos sean correspondientes, se pueden reconocer.

2. Atributos opcionales

  • A veces, algunos atributos de la interfaz no son necesarios. Solo necesita existir en algunos casos. Las interfaces con atributos opcionales solo necesitan agregar uno después de los atributos opcionales ?.
interface Person {
    
    
    name : string;
    age : number;
    phone? : number     
}

3. Atributos de solo lectura

  • Algunas propiedades del objeto solo se pueden modificar cuando el objeto se acaba de crear, y readonlylas propiedades de solo lectura se pueden especificar agregándolas delante del nombre de la propiedad .
interface Point {
    
    
    readonly x : number;
    readonly y : number;
}

let p : Point = {
    
     x : 5, y : 5};
p.x = 190;	// error,只能读不能赋值
  • Hay un ReadonlyArray<T>tipo en ts , que es Array<T>similar, excepto que se elimina el método que puede modificar la matriz, por lo que puede garantizar que la matriz no se modifique después de su creación:
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[];
  • Si se usa como variable, use const
  • Si se usa como atributo, use readonly

4. Comprobaciones de atributos adicionales

  • En el ejemplo anterior, pasamos un atributo que no está en la interfaz, y el resultado es que se ignora este atributo adicional; pero en una interfaz con atributos opcionales, esto fallará, lo que indica que no se espera el atributo adicional. Para omitir esta verificación, use aserciones de tipo.

    interface SquareConfig {
          
          
        color?: string;
        width?: number;
    }
    
    function createSquare(config: SquareConfig): {
          
           color: string; area: number } {
          
          
        // ...
    }
    
    let mySquare = createSquare({
          
           colour: "red", width: 100 } as SquareConfig);
    
  • Pero la mejor manera es agregar una firma de índice de cadena a la interfaz.

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

5. Tipo de función

  • Además de describir objetos ordinarios con atributos, las interfaces también pueden describir tipos de funciones; al definir una función, es necesario definir una firma de llamada, que es una definición de función con solo una lista de parámetros y un tipo de valor de retorno.

    interface searchFunc {
          
          
        (source : string, subString: string) : boolean;
    }
    
    let mysearch : searchFunc;
    mysearch = function (source : string,subString : string) {
          
          
        let result = source.search(subString);
        return result > -1;
    }
    
  • Para los tipos de función, los nombres de los parámetros de la función no necesitan ser consistentes con los de la interfaz. Los parámetros de la función se comprueban uno por uno y se requiere que los tipos de parámetros en las posiciones correspondientes sean compatibles. Si no especifica el tipo, TypeScript deducirá el tipo de parámetro. Si el tipo de valor de retorno de la función es diferente al de la interfaz, el verificador de tipos nos advertirá.

    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. Tipos indexables

  • El tipo indexable tiene una firma de índice, que describe el tipo de índice de objeto y el tipo de valor de retorno de índice correspondiente.

    interface StringArray{
          
          
        [index : number] : string;
    }
    
    let myarr : StringArray;
    myarr = ["yivi","huang"];
    
    let mystr : string = myarr[0];
    
  • TypeScript admite dos tipos de firmas de índice: cadena y número. Ambos tipos de índices se pueden usar al mismo tiempo, pero el valor de retorno de un índice numérico debe ser un subtipo del tipo de valor de retorno de un índice de cadena. Esto se debe a que al usar numberel tiempo para indexar, JavaScript lo convertirá para stringluego ir al objeto de índice. Es decir, usar 100(uno number) para indexar es equivalente a usar "100"(uno string) para indexar, por lo que los dos deben ser consistentes.

    class Animal {
          
          
        name: string;
    }
    class Dog extends Animal {
          
          
        breed: string;
    }
    
    // 错误:使用数值型的字符串索引,可能会以字符串进行索引,有时会得到完全不同的Animal!
    interface NotOkay {
          
          
        [x: number]: Animal;
        [x: string]: Dog;
    }
    
  • Las firmas de índice de cadena pueden describir dictionarybien los patrones y también garantizarán que todos los atributos coincidan con sus tipos de valor de retorno.

  • Porque el índice de cadena está declarado obj.propertyy obj["property"]las dos formas pueden serlo.

    interface NumberDictionary{
          
          
        [index: string] : number;
        length : number;	// ok,返回值与索引返回类型一致
        name : string;		// error,string与索引返回类型不一致
    }
    
  • Al mismo tiempo, también se puede decir que el tipo de índice está configurado como de solo lectura.

7. Clase

  • Al igual que Java, TypeScript también puede usar interfaces para aplicar propiedades o métodos que una clase debe implementar.

    interface clockInterface{
          
          
        currentTime : Date;
        setTime(d : Date);
    }
    
    class Clock implements clockInterface{
          
          
        currentTime : Date;
        setTime(d : Date){
          
          
            this.currentTime = d;
        }
        constructor(h : number,m : number){
          
          }
    }
    
  • Hay dos tipos de clases: tipo de pieza estática y tipo de instancia .

  • Al usar la firma del constructor para definir una interfaz y definir una clase para implementarla, se informará un error.

  • Porque cuando una clase implementa una interfaz, solo se verifica el tipo de su parte de instancia. El constructor existe en la parte estática de la clase, por lo que no está dentro del alcance de la inspección.

    // 以下定义会报错
    // 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);
    
  • Como createClockel primer parámetro es el ClockConstructortipo, en createClock(DigitalClock, 12, 17)él comprobará DigitalClocksi se ajusta a la firma del constructor.

8. Interfaz heredada

  • Al igual que Java, TypeScript también admite la herencia de interfaces;
  • Una interfaz puede heredar múltiples interfaces;

9. Tipos mixtos

  • La ventaja del mecanografiado es que es flexible y dinámico: un objeto se puede utilizar como función y como objeto al mismo tiempo, y tiene atributos adicionales.

    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. Clase de herencia de interfaz

  • Cuando una interfaz hereda una clase, heredará los miembros de la clase pero no su implementación. Significa que cuando crea una clase heredada de interfaz con variables privadas o protegidas, esta interfaz solo puede ser implementada por esta clase o sus subclases.

    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() {
          
           }
    }
    
    
  • Dentro de la Controlclase, se permite SelectableControlacceder a miembros privados a través de la instancia state. De hecho, la SelectableControlinterfaz y selectla Controlclase con métodos son las mismas.

Supongo que te gusta

Origin blog.csdn.net/yivisir/article/details/109552136
Recomendado
Clasificación