Guía de TS

Tabla de contenido

¿Qué es TS?

La relación entre TS y JS

Instalar TS

ver versión

compilar

Compilar en línea

Tipos de datos básicos de TS

tipo básico

tipo de referencia

Formación

tupla (tupla)

objeto

función

sobrecarga de funciones

tipo especial

cualquier

desconocido

enumeración numérica

tipo de inferencia

vacío

nunca

Enum (enumeración)

enumeración de cadenas

enumeración constante

enumeración heterogénea

tipo literal

Tipo de cruz (&)

Combinar atributos básicos con el mismo nombre

Combinar atributos no básicos con el mismo nombre

clase (clase)

método básico

campos privados (#)

Atributo de solo lectura (solo lectura)

Herencia (extiende)

modificador

abstracto

anulando y sobrecargando

tsconfig.json

Aserciones TS y protectores de tipo

aserción TS

tipo aserción

afirmación no nula

afirmación de asignación segura

doble afirmación

tipo de guardia

en palabra clave

tipo de palabra clave

interfaz de palabra clave

tipo predicado (es)

la diferencia entre los dos

alias de tipo, interfaces

alias de tipo (tipo)

interfaz

forma de objeto

heredar

interfaz de tipo de función

La diferencia entre tipo e interfaz.

tipo de datos básicos

expandir

Definición duplicada

Tipos de unión

Sindicato Discriminado

genérico

¿Por qué necesita genéricos?

sintaxis genérica

Múltiples tipos de paso de parámetros

interfaz genérica

clase genérica

alias de tipo genérico

Parámetros predeterminados genéricos

Letras comunes genéricas

habilidades comunes

extiende

tipo de

clave de

operador de acceso al índice

en

inferir

Parcial

Requerido

Solo lectura

Registro

Elegir

Excluir

Extra

Omitir

no anulable

Tipo de retorno

Parámetros

Fin

referencia:

resumen


¿Qué es TS?

TS : Abreviatura de TypeScript , es un lenguaje de programación gratuito y de código abierto desarrollado por Microsoft.

También puedes echar un vistazo a: Programación tipo TypeScript que no conoces

Tabla de contenido

¿Qué es TS?

La relación entre TS y JS

Instalar TS

ver versión

compilar

Compilar en línea

Tipos de datos básicos de TS

tipo básico

tipo de referencia

Formación

tupla (tupla)

objeto

función

sobrecarga de funciones

tipo especial

cualquier

desconocido

enumeración numérica

tipo de inferencia

vacío

nunca

Enum (enumeración)

enumeración de cadenas

enumeración constante

enumeración heterogénea

tipo literal

Tipo de cruz (&)

Combinar atributos básicos con el mismo nombre

Combinar atributos no básicos con el mismo nombre

clase (clase)

método básico

campos privados (#)

Atributo de solo lectura (solo lectura)

Herencia (extiende)

modificador

abstracto

anulando y sobrecargando

Aserciones TS y protectores de tipo

aserción TS

tipo aserción

afirmación no nula

afirmación de asignación segura

doble afirmación

tipo de guardia

en palabra clave

tipo de palabra clave

interfaz de palabra clave

tipo predicado (es)

la diferencia entre los dos

alias de tipo, interfaces

alias de tipo (tipo)

interfaz

forma de objeto

heredar

interfaz de tipo de función

La diferencia entre tipo e interfaz.

tipo de datos básicos

expandir

Definición duplicada

Tipos de unión

Sindicato Discriminado

genérico

¿Por qué necesita genéricos?

sintaxis genérica

Múltiples tipos de paso de parámetros

interfaz genérica

clase genérica

alias de tipo genérico

Parámetros predeterminados genéricos

Letras comunes genéricas

habilidades comunes

extiende

tipo de

clave de

operador de acceso al índice

en

inferir

Parcial

Requerido

Solo lectura

Registro

Elegir

Excluir

Extra

Omitir

no anulable

Tipo de retorno

Parámetros

Fin

referencia:

resumen


La relación entre TS y JS

Comparado con JS, TS es un superconjunto de JS En pocas palabras,  JavaScript agrega un sistema de tipo basado en , de modo que cada parámetro tenga un significado claro, lo que brinda indicaciones más inteligentes .

En términos relativos JS, TSes un lenguaje fuertemente tipado , por lo que para proyectos, hará que el código sea más estandarizado, resolviendo así la complejidad de los códigos de proyectos a gran escala.En segundo lugar, el navegador no lo reconoce, por lo que al compilar, TSel TSarchivo primero Compilar para JSarchivar.

Instalar TS

Ejecutando una orden:

$ npm install -g typescript 
 //或
$ yarn global add typescript

ver versión

$ tsc -v

compilar

$ tsc test.ts

# test.ts => test.js

Compilar en línea

Para mayor comodidad, podemos usar un editor en línea: TypeScript Playground[1], así

a97795fc0f27a2121ca9bf83aa9a54e3.png

 imagen.png

Y también puede echar un vistazo a las tsconversiones correspondientes generadas y los códigos posteriores ES5, ES6también hay ejemplos relacionados para que los vea.

Tipos de datos básicos de TS

Aquí, los tipos de datos de TS simplemente se clasifican de la siguiente manera:

  • Tipos básicos: string, number, boolean, symbol, bigint, null,undefined

  • Tipos de referencia: arrayTuple(tupla),  object(contiene Objecty {}),function

  • Tipos especiales: any, unknow, void, nerver, Enum(enumeración)

  • Otros tipos: 类型推理, 字面量类型,交叉类型

typeNota: y puede usarse en el caso interface, que se explicará en detalle a continuación. Si hay más vagos, puede echar un vistazo primero.

tipo básico

//字符串
    let str: string = "Domesy"
    
    // 数字
    let num: number = 7
    
    //布尔
    let bool: boolean = true
    
    //symbol
    let sym: symbol = Symbol();
     
    //bigint
    let big: bigint = 10n
        
    //null
    let nu: null = null
    
    //undefined
    let un: undefined = undefined

requiere atención:

  • null y  undefined dos tipos, una vez asignados, no se pueden asignar a ningún otro tipo

  • symboles único, asumiendo que está definiendo uno  sym1, entonces sym === sym1 es falso

tipo de referencia

Formación

Dos caminos:

  • escriba el nombre + []

  • Matriz<tipo de datos>

let arr1: number[] = [1, 2, 3]
    
let arr2: Array<number> = [1, 2, 3]
    
let arr2: Array<number> = [1, 2, '3'] // error
    
 //要想是数字类型或字符串类型,需要使用 |
let arr3: Array<number | string> = [1, 2, '3'] //ok

tupla (tupla)

 Se puede decir que  upleArray es  un caso especial de uple, por lo anterior  arr3podemos ver que su tipo puede ser stringo puede ser number, pero no hay una restricción específica para cada elemento.

Entonces  Tuple el papel es limitar el tipo de elementos y limitar el número de matrices.Al mismo tiempo,  Tupleeste valor de concepto existe TSy JSno existe en

Aquí hay un problema: en TS, se permite   aumentar  Tuplepush (es decir, permitir el uso de métodos), pero no se permite en acceso

let t: [number, string] = [1, '2'] // ok
    let t1: [number, string] = [1, 3] // error
    let t2: [number, string] = [1] // error
    let t3: [number, string] = [1, '1', true] // error
 
 
    let t5: [number, string] = [1, '2'] // ok
    t.push(2)
    console.log(t) // [1, '2', 2]
 
    let a =  t[0] // ok
    let b = t[1] // ok
    let c = t[2] // error

objeto

  • object Para tipos no primitivos, es posible usar el objeto directamente en la definición, pero informará un error si desea cambiar las propiedades del objeto. La razón es que no hay restricciones en las propiedades internas específicas del objeto. , por lo que debe usar {} para definir el   tipo interno

let obj1: object = { a: 1, b: 2}
    obj1.a = 3 // error
 
    let obj2: { a: number, b: number } = {a: 1, b: 2}
    obj2.a = 3 // ok

 Object(O mayúscula), lo que significa que se pueden asignar todos los tipos primitivos o no primitivos, excepto null`undefined

let obj: Object;
    obj = 1; // ok
    obj = "a"; // ok
    obj = true; // ok
    obj = {}; // ok
    obj = Symbol() //ok
    obj = 10n //ok
    obj = null; // error
    obj = undefined; // error

función

definir función

  • Hay dos formas, una es  functiony la otra es箭头函数

  • Al escribir, también puede escribir el tipo del valor de retorno. Si escribe, debe tener el valor de retorno del tipo correspondiente, pero generalmente se omite , porque TSla función de inferencia de tipo de la función puede inferir correctamente el tipo de valor de retorno.

function setName1(name: string) { //ok
      console.log("hello", name);
    }
    setName1("Domesy"); // "hello",  "Domesy"
 
    function setName2(name: string):string { //error
      console.log("hello", name);
    }
    setName2("Domesy");
 
    function setName3(name: string):string { //error
      console.log("hello", name);
      return 1
    }
    setName3("Domesy");
 
    function setName4(name: string): string { //ok
      console.log("hello", name);
      return name
    }
    setName4("Domesy"); // "hello",  "Domesy"
 
    //箭头函数与上述同理
    const setName5 = (name:string) => console.log("hello", name);
    setName5("Domesy") // "hello",  "Domesy"

Tipo de parámetro

  • Parámetros opcionales: si la función necesita configurar parámetros opcionales, se puede realizar con  ?  , y los parámetros opcionales deben estar al final

  • Parámetros predeterminados: puede configurar los parámetros predeterminados en la función usted mismo, use  =  para lograr

  • Parámetros restantes: el operador de propagación todavía se puede usar  ...

// 可选参数
    const setInfo1 = (name: string, age?: number) => console.log(name, age)
    setInfo1('Domesy') //"Domesy",  undefined
    setInfo1('Domesy', 7) //"Domesy",  7
 
    // 默认参数
    const setInfo2 = (name: string, age: number = 11) => console.log(name, age)
    setInfo2('Domesy') //"Domesy",  11
    setInfo2('Domesy', 7) //"Domesy",  7
 
    // 剩余参数
    const allCount = (...numbers: number[]) => console.log(`数字总和为:${numbers.reduce((val, item) => (val += item), 0)}`)
    allCount(1, 2, 3) //"数字总和为:6"

sobrecarga de funciones

Sobrecarga de funciones : es la capacidad de crear múltiples métodos con el mismo nombre y diferente número o tipo de parámetros. En TypeScript, esto se representa proporcionando varias definiciones de tipo de función para la misma función. En pocas palabras: puede definir múltiples tipos de valores bajo la misma función y finalmente agregarlos

let obj: any = {};
    function setInfo(val: string): void;
    function setInfo(val: number): void;
    function setInfo(val: boolean): void;
    function setInfo(val: string | number | boolean): void {
      if (typeof val === "string") {
        obj.name = val;
      } else {
        obj.age = val;
      }
    }
    setInfo("Domesy");
    setInfo(7);
    setInfo(true);
    console.log(obj); // { name: 'Domesy', age: 7 }

tipo especial

cualquier

En TS, se puede atribuir cualquier tipo al  any tipo, por lo que anyel tipo se convierte en el tipo principal de todos los tipos . Al mismo tiempo, si no se especifica el tipo de la variable, se establecerá de forma predeterminada en cualquier tipo . Por supuesto, este tipo no es recomendable, porque pierde el TS el papel de

let d:any; //等价于 let d 
    d = '1';
    d = 2;
    d = true;
    d = [1, 2, 3];
    d = {}

desconocido

Al igual que anycon y, se puede usar como el tipo de nivel superior de todos los tipos , pero  unknowes más estricto , por lo que se puede decir que es any el segundo tipo más grande, excepto por lo siguiente. A continuación, a modo de comparación any, es principalmente estricto en los dos puntos siguientes:

Al mismo tiempo, podemos ver cómo se ve la traducción en ES5

enumeración numérica

tipo de inferencia

Después de haber aprendido estos tipos básicos, ¿tenemos que escribir de qué tipo es el campo para cada tipo? En realidad no, TSsi no establece el tipo y no asigna un valor, se deducirá como cualquier tipo, y si asigna un valor, se establecerá por defecto en el tipo.

imagen.png
imagen.png
imagen.png
imagen.png
  • unknowSe comprobará el valor, pero anyno se comprobará el tipo. Para decirlo sin rodeos, anyel tipo se puede asignar a cualquier tipo, pero unknowsolo al unknowtipo y anyal tipo .

  • unknowCualquier operación (como método, nuevo, etc.) no está permitida en el valor definido, pero cualquiera puede

    let u:unknown;
        let a: any;
     
        u = '1'; //ok
        u = 2; //ok
        u = true; //ok
        u = [1, 2, 3]; //ok
        u = {}; //ok
     
        let value:any = u //ok
        let value1:any = a //ok
        let value2:unknown = u //ok
        let value3:unknown = a //ok
        let value4:string = u //error
        let value5:string = a //ok
        let value6:number = u //error
        let value7:number = a //ok
        let value8:boolean = u //error
        let value9:boolean = a //ok
     
        u.set() // error
        a.set() //ok
        u() // error
        a() //ok
        new u() // error
        new a() //ok

    vacío

    Cuando una función no tiene valor de retorno, TS predeterminará su valor de retorno para  void escribir

    const setInfo = ():void => {} // 等价于 const setInfo = () => {}
     
        const setInfo1 = ():void => { return '1' }  // error
        const setInfo2 = ():void => { return 2 } // error
        const setInfo3 = ():void => { return true } // error
        const setInfo4 = ():void => { return  } // ok
        const setInfo5 = ():void => { return undefined } //ok

    nunca

    Indica que una función nunca tendrá un valor de retorno, TS pensará que el tipo es  never, luego  void , en comparación,  neverdebería ser  voidun subconjunto, porque  voidel valor de retorno real  ni  siquiera  undefinedes neverundefined

    Las situaciones compatibles neverson: cuando se lanza una excepción y un bucle infinito

    let error = ():never => { // 等价约 let error = () => {}
                throw new Error("error");
        };
     
        let error1 = ():never => {
            while(true){}
        }

    Enum (enumeración)

    Las constantes con nombre se pueden definir para expresar la intención claramente o para crear un conjunto diferenciado de casos de uso

    Aviso:

  • El tipo de una enumeración sólo puede ser  string o number

  • El nombre definido no puede ser una palabra clave

  • El tipo del grupo de enumeración es el tipo de número por defecto, y por defecto comienza a acumularse desde 0. Si se establece el valor por defecto , solo afectará a los siguientes valores

  • Al mismo tiempo, se admite el mapeo inverso (y el mapeo del valor del miembro al nombre del miembro) , pero no hay un valor predeterminado para el mapeo inteligente y solo puede estar delante del valor predeterminado

  • editar

    enumeración de cadenas

    Tenga en cuenta que la enumeración de cadenas debe tener un valor predeterminado y no admite el mapeo inverso

    8ef7935a87cb22cdeab84f1ef963fcaf.png

    enumeración constante

    Además de 数字类型y 字符串类型, existe un tipo especial, es decir, la enumeración constante , que se constdefine mediante going enum, pero este tipo no se compilará en ningún  JS, solo se compilará el valor correspondiente

    bb6d3e56a011f17438923a90c5516d21.png

    enumeración heterogénea

    Contiene  una mezcla de 数字类型 y  字符串类型 , por la misma razón que el mapeo inverso

    7836aaa7fa320e9006561e2642543a60.png
let a; // 推断为any
    let str = '小杜杜'; // 推断为string
    let num = 13; // 推断为number
    let flag = false; // 推断为boolean
 
    str = true // error Type 'boolean' is not assignable to type 'string'.(2322)
    num = 'Domesy' // error
    flag = 7 // error

tipo literal

Tipo literal : En TS, podemos especificar el tipo del parámetro, actualmente admite 字符串, 数字, 布尔tres tipos. Por ejemplo, si defino  str 的类型是 '小杜杜' que el valor de str solo puede ser Xiaodudu

let str:'小杜杜' 
    let num: 1 | 2 | 3 = 1
    let flag:true
 
    str = '小杜杜' //ok
    str = 'Donmesy' // error
 
    num = 2 //ok
    num = 7 // error
 
    flag = true // ok
    flag = false // error

Tipo de cruz (&)

Tipo de intersección : combine varios tipos en uno solo, use &una conexión simbólica, como:

type AProps = { a: string }
    type BProps = { b: number }
 
    type allProps = AProps & BProps
 
    const Info: allProps = {
        a: '小杜杜',
        b: 7
    }

Combinar atributos básicos con el mismo nombre

Podemos ver 交叉类型que combina los valores de atributo de dos atributos, por lo que ahora tenemos un problema, si ambos atributos tienen el mismo valor de atributo, qué pasará con el tipo total en este momento, primero observe el siguiente caso:

type AProps = { a: string, c: number }
    type BProps = { b: number, c: string }
 
    type allProps = AProps & BProps
 
    const Info: allProps = {
        a: '小杜杜',
        b: 7,
        c:  1, // error (property) c: never
        c:  'Domesy', // error (property) c: never
    }

Si es del mismo tipo y el tipo fusionado también es este tipo, ¿qué sucede si es un tipo diferente?

Nos unimos tanto en Apropscomo con diferentes tipos, uno es de tipo y el otro es de tipoBPropsc属性c属性numberstring

¿Qué pasa con la combinación ahora  allProps ?¿Puede ser uno c属性 ambos, o solo uno de ellos number ? string

Sin embargo, en la práctica,  c pasar 数字类型y 字符串类型tampoco funcionará.Vemos un error, pero la realidad es que  el tipo de c nunca es .

Esto se debe a que el  catributo correspondiente es  string & number, pero obviamente este atributo no existe, por lo que cel atributo esnever

Combinar atributos no básicos con el mismo nombre

interface A { a: number }
    interface B { b: string }
 
    interface C {
        x: A
    }
    interface D {
        x: B
    }
    type allProps = C & D
 
    const Info: allProps = {
      x: {
        a: 7,
        b: '小杜杜'
      }
    }
 
    console.log(Info) // { x: { "a": 7, "b": "小杜杜" }}

Echemos un vistazo al caso: al mezclar varios tipos, si existe el mismo miembro y el tipo de miembro es un tipo de datos no básico, entonces la combinación puede ser exitosa.

Si b en la interfaz A también es del tipo número, se fusionará con el atributo básico del mismo nombre

clase (clase)

Presentó ES6un  class(类) gadget llamado , no voy a hablar de la definición específica, creo que Reactlos amigos que lo han usado deben estar familiarizados con él.

método básico

Entre los métodos básicos están: 静态属性, 静态方法, 成员属性, 成员方法, 构造器, get set方法, veámoslos uno por uno:

Cabe señalar que: en el atributo de miembro, si no proporciona el valor predeterminado y si no lo usa, se informará un error. Si no desea informar un error, proporcione como !  ,  como:name4!:string

class Info {
      //静态属性
      static name1: string = 'Domesy'
 
      //成员属性,实际上是通过public上进行修饰,只是省略了
      nmae2:string = 'Hello' //ok 
      name3:string //error
      name4!:string //ok 不设置默认值的时候必须加入 !
 
      //构造方法
      constructor(_name:string){
        this.name4 = _name
      }
 
      //静态方法
      static getName = () => {
        return '我是静态方法'
      }
 
      //成员方法
      getName4 = () => {
        return `我是成员方法:${this.name4}`
      }
 
      //get 方法
      get name5(){
        return this.name4
      }
 
      //set 方法
      set name5(name5){
        this.name4 = name5
      }
    }
 
    const setName = new Info('你好')
    console.log(Info.name1) //  "Domesy" 
    console.log(Info.getName()) // "我是静态方法" 
    console.log(setName.getName4()) // "我是成员方法:你好"

Veamos cómo se traduce el código anterior a ES5:

"use strict";
    var Info = /** @class */ (function () {
        //构造方法
        function Info(_name) {
            var _this = this;
            //成员属性
            this.nmae2 = 'Hello'; //ok
            //成员方法
            this.getName4 = function () {
                return "\u6211\u662F\u6210\u5458\u65B9\u6CD5:".concat(_this.name4);
            };
            this.name4 = _name;
        }
        Object.defineProperty(Info.prototype, "name5", {
            //get 方法
            get: function () {
                return this.name4;
            },
            //set 方法
            set: function (name5) {
                this.name4 = name5;
            },
            enumerable: false,
            configurable: true
        });
        //静态属性
        Info.name1 = 'Domesy';
        //静态方法
        Info.getName = function () {
            return '我是静态方法';
        };
        return Info;
    }());
    var setName = new Info('你好');
    console.log(Info.name1); //  "Domesy" 
    console.log(Info.getName()); // "我是静态方法" 
    console.log(setName.getName4()); // "我是成员方法:你好"

campos privados (#)

Los campos privados de ECMACMAScript se admiten desde TS 3.8 .

Cabe señalar que, 私有字段a diferencia de los campos regulares, las principales diferencias son:

  • Un campo privado  # comienza con un carácter, también llamado nombre privado;

  • Cada nombre de campo privado está calificado de forma única para la clase que lo contiene;

  • No puede usar modificadores de accesibilidad de TypeScript (como público o privado) en campos privados;

  • No se puede acceder a los campos privados fuera de la clase contenedora y ni siquiera se pueden detectar.

    class Info {
          #name: string; //私有字段
          getName: string;
     
          constructor(name: string) {
            this.#name = name;
            this.getName = name
          }
     
          setName() {
            return `我的名字是${this.#name}`
          }
        }
     
        let myName = new Info("Domesy");
     
     
        console.log(myName.setName()) // "我的名字是Domesy" 
        console.log(myName.getName) // ok "Domesy" 
        console.log(myName.#name) // error 
        // Property '#name' is not accessible outside class 'Info' 
        // because it has a private identifier.(18013)

    Atributo de solo lectura (solo lectura)

    Propiedades de solo lectura : con  readonlydecoración, solo se pueden inicializar en el constructor , y en TS, solo las propiedades en interface, se pueden identificar comotypeclassreadonly

  • readonlyRealmente solo está 编译阶段haciendo una revisión de código

  • Las palabras modificadas radonlysolo  constructorse pueden modificar en etapas y no se permite modificarlas en otros momentos.

    class Info {
          public readonly name: string; // 只读属性
          name1:string
     
          constructor(name: string) {
            this.name = name;
            this.name1 = name;
          }
     
          setName(name:string) {
            this.name = name // error
            this.name1 = name; // ok
          }
        }

    Herencia (extiende)

    Herencia : Es un punto más importante, lo que significa que el hijo puede heredar la idea del padre, es decir,  子类 después de la herencia 父类, tiene 父类los atributos y métodos, que es HOCalgo similar a

    Aquí hay otro supercampo, déjame contarte sobre él para aquellos que no saben, su función es llamar a las propiedades y métodos en la clase padre

    // 父类
        class Person {
          name: string
          age: number
     
          constructor(name: string, age:number){
            this.name = name
            this.age = age
          }
     
          getName(){
            console.log(`我的姓名是:${this.name}`)
            return this.name
          }
     
          setName(name: string){
            console.log(`设置姓名为:${name}`)
            this.name = name
          }
        }
     
        // 子类
        class Child extends Person {
          tel: number
          constructor(name: string, age: number, tel:number){
            super(name, age)
            this.tel = tel
          }
     
          getTel(){
            console.log(`电话号码是${this.tel}`)
            return this.tel
          }
        }
     
        let res = new Child("Domesy", 7 , 123456)
        console.log(res) // Child {."name": "Domesy", "age": 7, "no": 1 }
        console.log(res.age) // 7
        res.setName('小杜杜') // "设置姓名为:小杜杜" 
        res.getName() //   "我的姓名是:小杜杜"
        res.getTel() //  "电话号码是123456"

    modificador

    Hay tres modificadores principales:

  • public : se puede llamar en cualquier lugar de la clase, en la subclase y fuera

  • protected : se puede llamar en cualquier lugar de la clase o subclase, pero no se puede llamar fuera

    • privado : se puede llamar en la clase y no se puede llamar en ningún lugar de la subclase o fuera

      class Person {
            public name: string
            protected age: number
            private tel: number
       
            constructor(name: string, age:number, tel: number){
              this.name = name
              this.age = age
              this.tel = tel
            }
          }
       
          class Child extends Person {
            constructor(name: string, age: number, tel: number) {
              super(name, age, tel);
            }
       
            getName(){
              console.log(`我的名字叫${this.name},年龄是${this.age}`) // ok name 和 age可以
              console.log(`电话是${this.tel}`) // error 报错 原因是 tel 拿不出来
            }
          }
       
       
          const res = new Child('Domesy', 7, 123456)
          console.log(res.name) // ok Domesy
          console.log(res.age) // error
          console.log(res.tel) // error

      abstracto

      abstract : una clase declarada con la palabra clave abstract se denomina clase abstracta , y el método declarado se denomina método abstracto.

    • Clase abstracta : significa que no se puede instanciar porque contiene uno o más métodos abstractos.

    • Método abstracto : se refiere a un método que no contiene una implementación específica;

    • Nota: las clases abstractas no se pueden instanciar directamente, solo se pueden instanciar las subclases que implementan todos los métodos abstractos.

abstract class Person {
      constructor(public name: string){}
 
      // 抽象方法
      abstract setAge(age: number) :void;
    }
 
    class Child extends Person {
      constructor(name: string) {
        super(name);
      }
 
      setAge(age: number): void {
        console.log(`我的名字是${this.name},年龄是${age}`);
      }
    }
 
    let res = new Person("小杜杜") //error
    let res1 = new Child("小杜杜");
 
    res1.setAge(7) // "我的名字是小杜杜,年龄是7"

anulando y sobrecargando

  • Anular : la subclase anula el método heredado de la clase principal

  • Sobrecarga : se refiere a proporcionar múltiples definiciones de tipo para la misma función, similar a la sobrecarga de las funciones anteriores.

    // 重写
        class Person{
          setName(name: string){
            return `我的名字叫${name}`
          }
        }
     
        class Child extends Person{
          setName(name: string){
            return `你的名字叫${name}`
          }
        }
     
        const yourName = new Child()
        console.log(yourName.setName('小杜杜')) // "你的名字叫小杜杜" 
     
        // 重载
        class Person1{
          setNameAge(name: string):void;
          setNameAge(name: number):void;
          setNameAge(name:string | number){
            if(typeof name === 'string'){
              console.log(`我的名字是${name}`)
            }else{
              console.log(`我的年龄是${name}`)
            }
          };
        }
     
        const res = new Person1()
        res.setNameAge('小杜杜') // "我的名字是小杜杜" 
        res.setNameAge(7) // "我的年龄是7"

    tsconfig.json

    tsconfig.json contiene   configuraciones relacionadas con la compilación de TypeScript . Al cambiar los elementos de configuración de compilación, podemos hacer que TypeScript compile ES6, ES5 y códigos de nodo.

    campo importante

    files - 设置要编译的文件的名称;
    include - 设置需要进行编译的文件,支持路径模式匹配;
    exclude - 设置无需进行编译的文件,支持路径模式匹配;
    compilerOptions - 设置与编译流程相关的选项。
    

    opción compilerOptions

    {
      "compilerOptions": {
      
        /* 基本选项 */
        "target": "es5",                       // 指定 ECMAScript 目标版本: 'ES3' (default), 'ES5', 'ES6'/'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'
        "module": "commonjs",                  // 指定使用模块: 'commonjs', 'amd', 'system', 'umd' or 'es2015'
        "lib": [],                             // 指定要包含在编译中的库文件
        "allowJs": true,                       // 允许编译 javascript 文件
        "checkJs": true,                       // 报告 javascript 文件中的错误
        "jsx": "preserve",                     // 指定 jsx 代码的生成: 'preserve', 'react-native', or 'react'
        "declaration": true,                   // 生成相应的 '.d.ts' 文件
        "sourceMap": true,                     // 生成相应的 '.map' 文件
        "outFile": "./",                       // 将输出文件合并为一个文件
        "outDir": "./",                        // 指定输出目录
        "rootDir": "./",                       // 用来控制输出目录结构 --outDir.
        "removeComments": true,                // 删除编译后的所有的注释
        "noEmit": true,                        // 不生成输出文件
        "importHelpers": true,                 // 从 tslib 导入辅助工具函数
        "isolatedModules": true,               // 将每个文件做为单独的模块 (与 'ts.transpileModule' 类似).
    
        /* 严格的类型检查选项 */
        "strict": true,                        // 启用所有严格类型检查选项
        "noImplicitAny": true,                 // 在表达式和声明上有隐含的 any类型时报错
        "strictNullChecks": true,              // 启用严格的 null 检查
        "noImplicitThis": true,                // 当 this 表达式值为 any 类型的时候,生成一个错误
        "alwaysStrict": true,                  // 以严格模式检查每个模块,并在每个文件里加入 'use strict'
    
        /* 额外的检查 */
        "noUnusedLocals": true,                // 有未使用的变量时,抛出错误
        "noUnusedParameters": true,            // 有未使用的参数时,抛出错误
        "noImplicitReturns": true,             // 并不是所有函数里的代码都有返回值时,抛出错误
        "noFallthroughCasesInSwitch": true,    // 报告 switch 语句的 fallthrough 错误。(即,不允许 switch 的 case 语句贯穿)
    
        /* 模块解析选项 */
        "moduleResolution": "node",            // 选择模块解析策略: 'node' (Node.js) or 'classic' (TypeScript pre-1.6)
        "baseUrl": "./",                       // 用于解析非相对模块名称的基目录
        "paths": {},                           // 模块名到基于 baseUrl 的路径映射的列表
        "rootDirs": [],                        // 根文件夹列表,其组合内容表示项目运行时的结构内容
        "typeRoots": [],                       // 包含类型声明的文件列表
        "types": [],                           // 需要包含的类型声明文件名列表
        "allowSyntheticDefaultImports": true,  // 允许从没有设置默认导出的模块中默认导入。
    
        /* Source Map Options */
        "sourceRoot": "./",                    // 指定调试器应该找到 TypeScript 文件而不是源文件的位置
        "mapRoot": "./",                       // 指定调试器应该找到映射文件而不是生成文件的位置
        "inlineSourceMap": true,               // 生成单个 soucemaps 文件,而不是将 sourcemaps 生成不同的文件
        "inlineSources": true,                 // 将代码与 sourcemaps 生成到一个文件中,要求同时设置了 --inlineSourceMap 或 --sourceMap 属性
    
        /* 其他选项 */
        "experimentalDecorators": true,        // 启用装饰器
        "emitDecoratorMetadata": true          // 为装饰器提供元数据的支持
      }
    }
    

  • Aserciones TS y protectores de tipo

    aserción TS

    Se divide en tres tipos: 类型断言, 非空断言,确定赋值断言

    Cuando la aserción falla, se puede usar: doble aserción

    tipo aserción

    En un entorno específico, conoceremos el tipo específico de este valor mejor que TS, y no necesitamos que TS juzgue. El entendimiento simple es que la aserción de tipo le dirá al compilador que no necesita verificarlo. Créeme , es de este tipo.

    Hay dos maneras:

  • Paréntesis angulares

  • como : recomendado

    //尖括号
       let num:any = '小杜杜'
       let res1: number = (<string>num).length; // React中会 error
     
       // as 语法
       let str: any = 'Domesy';
       let res: number = (str as string).length;

    Pero debe tenerse en cuenta que la sintaxis del corchete angular informará un error en React , porque JSXentrará en conflicto con la sintaxis, por lo que solo puede usar la sintaxis as

    afirmación no nula

    Se puede usar un nuevo operador de expresión de postfijo  ! para afirmar que los operandos no son nulos ni indefinidos en contextos donde el verificador de tipos no puede determinar el tipo.

    ES5El código que comparamos

    e0bfa6ce09c47ee51a3c5f47b86c6bc7.pngimagen.png

    Podemos ver que  !nos puede ayudar a filtrar  nullundefinedescribir, es decir, el compilador por defecto solo pasará stringel tipo de datos, por lo que se puede asignar comostr1

    Pero se eliminará  ES5después  de convertirse, por lo que cuando se transfiera  , aún se reproducirá. !nullnull

    afirmación de asignación segura

    La aserción de asignación definitiva se introdujo en TS la versión 2.7, que permite colocar un número después del atributo de instancia y la declaración de variable  ! para indicar TSque el atributo se asignará definitivamente.

    let num: number;
        let num1!: number;
     
        const setNumber = () => num = 7
        const setNumber1 = () => num1 = 7
     
        setNumber()
        setNumber1()
     
        console.log(num) // error 
        console.log(num1) // ok

    doble afirmación

    Después de que falla la aserción, se puede usar, pero generalmente no se usará

    Caso de falla: el tipo subyacente no se puede afirmar como una interfaz

    interface Info{
          name: string;
          age: number;
        }
     
        const name = '小杜杜' as Info; // error, 原因是不能把 string 类型断言为 一个接口
        const name1 = '小杜杜' as any as Info; //ok

    tipo de guardia

    Tipo de protección : una expresión que puede realizar comprobaciones en tiempo de ejecución para asegurarse de que el tipo está dentro de un rango determinado .

    Mi sensación personal es que type guard significa que puede configurar varios tipos, pero prefiero a qué tipo se refiere

    En la actualidad, hay cuatro guardias de tipos comunes: palabra clave in , palabra clave typeof , palabra clave interfaceof y predicado de tipo (es)

    en palabra clave

    Se utiliza para juzgar si este atributo está en ese

    interface Info {
          name: string
          age: number
        }
     
        interface Info1{
          name: string
          flage: true
        }
     
        const setInfo = (data: Info | Info1) => {
          if("age" in data){
            console.log(`我的名字是:${data.name},年龄是:${data.age}`)
          }
     
           if("flage" in data){
            console.log(`我的名字是:${data.name},性别是:${data.flage}`)
          }
        }
     
        setInfo({name: '小杜杜', age: 7}) // "我的名字是:小杜杜,年龄是:7" 
        setInfo({name: '小杜杜', flage: true}) // "我的名字是:小杜杜,性别是:true"

    tipo de palabra clave

    Se utiliza para juzgar tipos básicos, como cadena | número, etc.

    const setInfo = (data: number | string | undefined) => {
          if(typeof data === "string"){
            console.log(`我的名字是:${data}`)
          }
     
          if(typeof data === "number"){
            console.log(`我的年龄是:${data}`)
          }
     
          if(typeof data === "undefined"){
            console.log(data)
          }
        }
     
        setInfo('小杜杜') // "我的名字是:小杜杜"  
        setInfo(7) // "我的年龄是:7" 
        setInfo(undefined) // undefined"

    interfaz de palabra clave

    Se usa para determinar si una instancia es un constructor o cuando se usa una clase

    class Name {
          name: string = '小杜杜'
        }
     
        class Age extends Name{
          age: number = 7
        }
     
        const setInfo = (data: Name) => {
          if (data instanceof Age) {
            console.log(`我的年龄是${data.age}`);
          } else {
            console.log(`我的名字是${data.name}`);
          }
        } 
     
        setInfo(new Name()) // "我的名字是小杜杜"
        setInfo(new Age()) // "我的年龄是7"

    tipo predicado (es)

    function isNumber(x: any): x is number { //默认传入的是number类型
      return typeof x === "number"; 
    }
     
    console.log(isNumber(7)) // true
    console.log(isNumber('7')) //false
    console.log(isNumber(true)) //false

    la diferencia entre los dos

    A través de la introducción anterior, podemos encontrar que el concepto de 断言y 类型守卫es muy similar para determinar el tipo de parámetro, pero es 断言más autoritario.Le dice directamente al editor que el parámetro es de este tipo, y type guard es más como determinar de qué tipo es el parámetro. . (Entendimiento personal, si hay algo mal, indíquelo ~)

    alias de tipo, interfaces

    alias de tipo (tipo)

    alias de tipo : es decir type, se utiliza para dar un nuevo nombre a un tipo

    type InfoProps = string | number
        
        const setInfo = (data: InfoProps) => {}

    interfaz

    Interfaz : representa abstracciones de comportamiento en lenguajes orientados a objetos y también se puede utilizar para describir la forma de los objetos.

    Use la palabra clave de interfaz para definir una interfaz

    forma de objeto

    La interfaz se puede utilizar para describir 对象, incluyendo principalmente los siguientes datos: 可读属性, 只读属性,任意属性

  • Atributos legibles : cuando definimos una interfaz, es posible que nuestros atributos no necesiten ser todos, ¿esta es la   necesidad ?

  • Atributo de solo lecturael atributo modificado con solo lectura es un atributo de solo lectura, lo que significa que se puede definir y no se puede cambiar más adelante.

  • Atributo arbitrario : este atributo es extremadamente importante, se puede usar incluso si no está definido, como  [datos: cadena]: cualquiera . Por ejemplo, si encapsulamos un componente, y el componente encapsulado no exporta el tipo correspondiente, pero queremos que no reporte un error, entonces podemos usar cualquier atributo

    interface Props {
            a: string;
            b: number;
            c: boolean;
            d?: number; // 可选属性
            readonly e: string; //只读属性
            [f: string]: any //任意属性
        }
        let res: Props = {
            a: '小杜杜',
            b: 7,
            c: true,
            e: 'Domesy',
            d: 1, // 有没有d都可以
            h: 2 // 任意属性,之前为定义过h
        }
     
        let res.e = 'hi' // error, 原因是可读属性不允许更改

    índice de firma

  • Definición: las firmas de índice se utilizan para describir tipos que se "recuperan mediante indexación"
  • Formato: como[props: string]:any
  • Escenario de aplicación: resolución de problemas de parámetros
    export default {}
    
    interface IFullName {
      firstName: string
      lastName : string
      age?: number
      singName?: string
      [props: string]: any
    }
    
    // 注意点: 如果使用接口来限定了变量或者形参, 那么在给变量或者形参赋值的时候,多一个或者少一个都不行
    // 实际开发中往往会出现多或者少的情况,怎么解决?
    
    
    // 少一个或者少多个属性
    // 解决方案: 可选属性
    let goddass1:IFullName = {firstName: "邱", lastName: "淑贞"};
    let goddass2:IFullName = {firstName: "邱", lastName: "淑贞", age: 18};
    
    
    // 多一个或者多多个属性
    // 方案一:使用变量
    let info = {firstName: "邱", lastName: "淑贞", age: 18, singName: "赌王", dance: "芭蕾"};
    let goddass3:IFullName = info
    
    // 方案二: 使用类型断言
    let goddass4:IFullName = ({firstName: "邱", lastName: "淑贞", age: 18, singName: "赌王", dance: "芭蕾"}) as IFullName;
    
    
    
    
    // 索引签名?
    // 索引签名用于描述那些“通过索引得到”的类型
    // 注意点: 对象中的键,会被转化为字符串
    interface Ibeauty {
      [props: string]: string
    }
    
    let name:Ibeauty = {name1: "邱淑贞", name2: "李嘉欣", name3: "周慧敏"};
    
    
    interface Iage {
      [props: string]: number
    }
    
    let afe:Iage = {age1: 18, age2: 20};
    
    
    
    
    
    
    
    // 方案三: 索引签名
    let goddass5:IFullName = {firstName: "邱", lastName: "淑贞", age: 18, singName: "赌王", dance: "芭蕾"};
    

  • heredar

    Herencia : al igual que las clases, las interfaces también tienen propiedades heredadas y extendscampos de uso.

    interface nameProps {
            name: string
        }
     
        interface Props extends nameProps{
            age: number
        }
     
        const res: Props = {
            name: '小杜杜',
            age: 7
        }

    interfaz de tipo de función

    Al mismo tiempo, puede definir funciones y clases, agregar clasesnew modificadas y no agregar nuevas funciones

    interface Props {
            (data: number): number
        }
     
        const info: Props = (number:number) => number  //可定义函数
     
        // 定义函数
        class A {
            name:string
            constructor(name: string){
                this.name = name
            }
        }
     
        interface PropsClass{
            new (name: string): A
        }
     
        const info1 = (fun: PropsClass, name: string) => new fun(name)
     
        const res = info1(A, "小杜杜")
        console.log(res.name) // "小杜杜"

    La diferencia entre tipo e interfaz.

    A través del estudio anterior, encontramos que 类型别名y 接口son muy similares, se puede decir que en la mayoría de los casos, typey interfaceson equivalentes

    Sin embargo, en algunos escenarios específicos, la brecha sigue siendo relativamente grande. Veámoslos uno por uno.

    tipo de datos básicos

  • typey interfaceambos pueden definir  objetos  y  funciones

  • typePuede definir otros tipos de datos, como cadenas, números, tuplas, tipos de unión, etc., pero interfaceno

    type A = string // 基本类型
     
        type B = string | number // 联合类型
     
        type C = [number, string] // 元祖
     
        const dom = document.createElement("div");  // dom元素
        type D = typeof dom

    expandir

    interface Se puede extender  typey type también se puede extender como  interface, pero los dos implementan la extensión de diferentes maneras.

  • interface se  extends logra a través

  • type se  & logra a través

    // interface 扩展 interface
        interface A {
            a: string
        }
        interface B extends  A {
            b: number
        }
        const obj:B = { a: `小杜杜`, b: 7 }
     
        // type 扩展 type
        type C = { a: string }
        type D = C & { b: number }
        const obj1:D = { a: `小杜杜`, b: 7 }
     
        // interface 扩展为 Type
        type E = { a: string }
        interface F extends E { b: number }
        const obj2:F = { a: `小杜杜`, b: 7 }
     
        // type 扩展为 interface
        interface G { a: string }
        type H = G & {b: number}
        const obj3:H = { a: `小杜杜`, b: 7 }

    Definición duplicada

    interface se puede definir varias veces y se fusionará, pero typeno

    interface A {
            a: string
        }
        interface A {
            b: number
        }
        const obj:A = { a: `小杜杜`, b: 7 }
     
        type B = { a: string }
        type B = { b: number } // error

    Tipos de unión

    Tipos de unión  : indica que el valor puede ser uno de varios tipos. Cuando no se asigna ningún valor, solo se puede acceder a los atributos y métodos compartidos por los dos tipos en el tipo de unión, como:

    const setInfo = (name: string | number) => {}
     
        setInfo('小杜杜')
        setInfo(7)

    setInfoReciba uno de los anteriores  name, pero  name puede recibir  stringo numberescribir, entonces este parámetro es un tipo conjunto

    Sindicato Discriminado

    Unión discriminada : contiene tres características, a saber 可辨识, , 联合类型, 类型守卫,

    La esencia de este tipo es: un método de protección de tipos que combina tipos de unión y tipos literales .

    Si un tipo es un tipo conjunto de varios tipos y varios tipos contienen un atributo común, este atributo común se puede usar para crear diferentes bloques de protección de tipos.

    Es decir, los anteriores se usan juntos, aquí hay un pequeño ejemplo:

    interface A {
          type: 1,
          name: string
        }
     
        interface B {
          type: 2
          age: number
        }
     
        interface C {
          type: 3,
          sex: boolean
        }
     
        // const setInfo = (data: A | B | C) => {
        //   return data.type // ok 原因是 A 、B、C 都有 type属性
        //   return data.age // error,  原因是没有判断具体是哪个类型,不能确定是A,还是B,或者是C
        // }
     
        const setInfo1 = (data: A | B | C) => {
          if (data.type === 1 ) {
            console.log(`我的名字是${data.name}`);
          } else if (data.type === 2 ){
            console.log(`我的年龄是${data.age}`);
          } else if (data.type === 3 ){
            console.log(`我的性别是${data.sex}`);
          }
        }
     
        setInfo1({type: 1, name: '小杜杜'}) // "我的名字是小杜杜"
        setInfo1({type: 2, age: 7}) // "我的年龄是7" 
        setInfo1({type: 3, sex: true}) // "我的性别是true"

    A, By tres interfaces están definidas  C , pero las tres interfaces contienen typeatributos, de modo typeque 可辨识的属性, y otros atributos solo están relacionados con la interfaz de la función.

    Luego, a través de los atributos identificables type, se pueden usar sus atributos relacionados

    genérico

    Genéricos : los genéricos se refieren a una característica que no especifica un tipo específico de antemano al definir una función, interfaz o clase, pero especifica el tipo al usarlo

    En otras palabras, los genéricos son una plantilla que permite que la con. Comparadomisma función acepte diferentes tipos de parámetrosany

    ¿Por qué necesita genéricos?

    Veamos primero un ejemplo:

    const calcArray = (data:any):any[] => {
            let list = []
            for(let i = 0; i < 3; i++){
                list.push(data)
            }
            return list
        }
     
        console.log(calcArray('d')) // ["d", "d", "d"]

    En el ejemplo anterior, encontramos que calcArraysi se pasa cualquier tipo de parámetro, la matriz devuelta es anydel tipo

    Como no sabemos cuáles son los datos entrantes, los datos devueltos también sonany的数组

    Pero el efecto que queremos ahora es: no importa qué tipo pasemos, se puede devolver el tipo correspondiente ¿Qué debemos hacer en este caso? Así que aquí 泛型está

    sintaxis genérica

    Primero modifiquemos el ejemplo anterior con genéricos,

    const calcArray = <T,>(data:T):T[] => {
            let list:T[] = []
            for(let i = 0; i < 3; i++){
                list.push(data)
            }
            return list
        }
     
        const res:string[] = calcArray<string>('d') // ok
        const res1:number[] = calcArray<number>(7) // ok
     
        type Props = {
            name: string,
            age: number
        }
        const res3: Props[] = calcArray<Props>({name: '小杜杜', age: 7}) //ok

    Después del caso anterior, encontramos que el entrante 字符串, 数字, 对象, puede devolver el tipo correspondiente, para lograr nuestro objetivo, echemos un vistazo a continuación 泛型语法:

    function identity <T>(value:T) : T {
            return value
        }

    Múltiples tipos de paso de parámetros

    Tenemos múltiples marcadores de posición de tipo desconocido, podemos definir cualquier letra para representar diferentes tipos de parámetros

    const calcArray = <T,U>(name:T, age:U): {name:T, age:U} => {
            const res: {name:T, age:U} = {name, age}
            return res
        }
     
        const res = calcArray<string, number>('小杜杜', 7)
        console.log(res) // {"name": "小杜杜", "age": 7}

    interfaz genérica

    Al definir interfaces, también podemos usar genéricos

    interface A<T> {
            data: T
        }
     
        const Info: A<string> = {data: '1'}
        console.log(Info.data) // "1"

    clase genérica

    Los genéricos también pueden definir clases.

    class clacArray<T>{
            private arr: T[] = [];
     
            add(value: T) {
                this.arr.push(value)
            }
            getValue(): T {
                let res = this.arr[0];
                console.log(this.arr)
                return res;
            }
        }
     
        const res = new clacArray()
     
        res.add(1)
        res.add(2)
        res.add(3)
     
        res.getValue() //[1, 2, 3] 
        console.log(res.getValue) // 1

    alias de tipo genérico

    type Info<T> = {
            name?: T
            age?: T
        }
     
        const res:Info<string> = { name: '小杜杜'}
        const res1:Info<number> = { age: 7}

    Parámetros predeterminados genéricos

    El denominado parámetro predeterminado es el tipo especificado. Al igual que el valor predeterminado, cuando el tipo no se puede inferir del parámetro de valor real, este tipo predeterminado funcionará.

    const calcArray = <T = string,>(data:T):T[] => {
            let list:T[] = []
            for(let i = 0; i < 3; i++){
                list.push(data)
            }
            return list
        }

    Letras comunes genéricas

    Use letras de uso común para indicar algunas representaciones variables:

  • T : significa Tipo , generalmente se usa como el primer nombre de variable de tipo al definir genéricos

  • K : significa Clave , que indica el tipo de clave en el objeto ;

  • V : significa Valor , indicando el tipo de valor en el objeto ;

  • E : significa Elemento , el tipo de elemento representado ;

habilidades comunes

Hay muchas palabras clave y tipos de herramientas en TS. Al usarlas, debe prestar atención a la aplicación de genéricos . A veces puede haber ciertos problemas en la combinación.

Se debe prestar especial atención a  los tipos de herramientas extends, typeof, Partial, Record, Exclude,Omit

extiende

extends : Comprobar si posee sus atributos, aquí por ejemplo conocemos 字符串y 数组poseemos lengthatributos, pero numberno tenemos este atributo.

const calcArray = <T,>(data:T): number => {
      return data.length // error 
    }

calcArrayLa función de lo anterior  es solo obtener data的数量, pero en este momento TSse reportará un error en .Esto se debe a que TS no está seguro si el atributo pasado tiene el atributo de longitud .Después de todo, cada atributo no puede ser exactamente igual

Entonces, ¿cómo resolverlo en este momento?

Ya hemos determinado que para obtener los datos pasados  length, es decir, el atributo pasado debe tener lengtheste atributo, si no, no se le permitirá llamar a este método.

En otras palabras, calcArrayes necesario tener la función de verificar atributos, para el ejemplo anterior es verificar si lengthhay una función, es por eso que necesitamos el atributo de extends para ayudarnos a identificar:

interface Props {
        length: number
    }
 
    const calcArray = <T extends Props,>(data:T): number => {
      return data.length // error
    }
 
    calcArray('12') // ok
    calcArray([1,3]) //ok
    calcArray(2) //error

Se puede ver calcArray(2)que se reportará un error porque numberel tipo no tiene lengthesta propiedad

tipo de

palabra clave typeof : explicamos la función de typeof en la protección de tipos. Además, esta palabra clave también puede realizar la introducción de tipos , como se muestra en la figura a continuación, que puede inferir  los tipos contenidos en Props

clave de

palabra clave keyof : puede obtener todos keylos valores de una interfaz de objeto y puede verificar si existe la clave en el objeto

interface Props {
        name: string;
        age: number;
        sex: boolean
    }
 
    type PropsKey = keyof Props; //包含 name, age, sex
 
    const res:PropsKey = 'name' // ok
    const res1:PropsKey = 'tel' // error
 
    // 泛型中的应用
    const getInfo = <T, K extends keyof T>(data: T, key: K): T[K] => {
        return data[key]
    }
 
    const info = {
        name: '小张',
        age: 7,
        sex: true
    }
 
    getInfo(info, 'name'); //ok
    getInfo(info, 'tel'); //error

operador de acceso al índice

Operador de acceso al índice : el acceso al índice se puede realizar a través  del operador []  , y se puede acceder a una de las propiedades

en

en : tipo de mapeo, utilizado para mapear y atravesar tipos de enumeración

inferir

infer : se puede usar como una declaración condicional y se puede usar para  infer declarar una variable de tipo y usarla. como

type Info<T> = T extends { a: infer U; b: infer U } ? U : never;
 
    type Props = Info<{ a: string; b: number }>; // Props类:string | number
 
    type Props1 = Info<number> // Props类型:never

Parcial

Sintaxis parcial : Partial<T> Función: ¿Hacer que todos los atributos sean opcionales  ?

interface Props {
        name: string,
        age: number
    }
 
    const info: Props = {
        name: '小王',
        age: 7
    }
 
    const info1: Partial<Props> = { 
        name: '小徐'
    }

Del código anterior, se requieren el nombre y la edad. Para información, se deben establecer los atributos de nombre y edad, pero para info1, siempre que sea un objeto, no es importante si hay atributos de nombre y edad.

Requerido

Sintaxis requerida : Required<T> Función: hacer que todos los atributos sean obligatorios y  Partiallo contrario

interface Props {
        name: string,
        age: number,
        sex?: boolean
    }
 
    const info: Props = {
        name: '小王',
        age: 7
    }
 
    const info1: Required<Props> = { 
        name: '小徐',
        age: 7,
        sex: true
    }

Solo lectura

Sintaxis de solo lectura : Readonly<T> Función: agregue el modificador de solo lectura a todos los atributos para lograr. Es decir, no se puede modificar.

interface Props {
        name: string
        age: number
    }
 
    let info: Readonly<Props> = {
        name: '小徐',
        age: 7
    }
 
    info.age = 1 //error read-only 只读属性

A juzgar por el código anterior,  Readonlydespués de la modificación, el atributo no se puede cambiar de nuevo, uso inteligente

Registro

Sintaxis de registro : Record<K extiende keyof any, T>

Función: Convierte  K los valores de todos los atributos del tipo en  T tipos.

interface Props {
        name: string,
        age: number
    }
 
    type InfoProps = 'JS' | 'TS'
 
    const Info: Record<InfoProps, Props> = {
        JS: {
            name: '小徐',
            age: 7
        },
        TS: {
            name: 'TypeScript',
            age: 11
        }
    }

A juzgar por el código anterior,  InfoPropslas propiedades de las propiedades contienen respectivamente Propslas propiedades

Una cosa a tener en cuenta es: K extends keyof anysu tipo puede ser: string, number,symbol

Elegir

Sintaxis de selección : Pick<T, K extiende la clave de T>

Función: seleccione los subatributos de un determinado tipo y conviértalos en subtipos que contengan algunas propiedades de este tipo.

interface Props {
        name: string,
        age: number,
        sex: boolean
    }
 
    type nameProps = Pick<Props, 'name' | 'age'>
 
    const info: nameProps = {
        name: '小徐',
        age: 7
    }

Del código anterior,  Propslos atributos originales incluyen name, agey sextres atributos.  Los seleccionamos a través de Pick, por lo que no sename necesitan atributos .agesex

Excluir

Excluir语法:Excluir<T, U>

Función: Elimina el tipo U en el tipo T.

// 数字类型
    type numProps = Exclude<1 | 2 | 3, 1 | 2> // 3
    type numProps1 = Exclude<1, 1 | 2> // nerver
    type numProps2 = Exclude<1, 1> // nerver
    type numProps3 = Exclude<1 | 2, 7> // 1 2
 
    // 字符串类型
    type info = "name" | "age" | "sex"
    type info1 = "name" | "age" 
    type infoProps = Exclude<info, info1> //  "sex"
 
    // 类型
    type typeProps = Exclude<string | number | (() => void), Function> // string | number
 
    // 对象
    type obj = { name: 1, sex: true }
    type obj1 = { name: 1 }
    type objProps = Exclude<obj, obj1> // nerver

Del código anterior, comparamos los tipos. Cuando hay U en T, se eliminará el atributo correspondiente. Si no hay ningún atributo en U en T, o T y U son exactamente iguales, volverá al nervio, y  el objeto siempre regresanerver

Extra

Extra语法:Extra<T, U>

Función: Extrae U de los tipos a los que se puede asignar T. Contrario Excluir

type numProps = Extract<1 | 2 | 3, 1 | 2> // 1 | 2

Omitir

Omitir sintaxis : Omitir <T, U>

Función: eliminar los atributos del tipo declarado para obtener un nuevo tipo

La diferencia con  Excluir : Omitir devuelve un nuevo tipo, que se  Excludebasa en el principio, y Excludese devuelve según el tipo propio

no anulable

Sintaxis no anulable : rol: excluir  y  NonNullable<T> de T nullundefined

Tipo de retorno

Sintaxis de tipo de retorno :ReturnType<T>

Función: Se utiliza para obtener  el tipo de retorno de la función T.

type Props = ReturnType<() => string> // string
    type Props1 = ReturnType<<T extends U, U extends number>() => T>; // number
    type Props2 = ReturnType<any>; // any
    type Props3 = ReturnType<never>; // any

Del código anterior, ReturnType puede aceptar cualquier tipo y nunca, porque estos dos tipos pertenecen al tipo de nivel superior y contienen funciones

Parámetros

Parámetros : Parameters<T> Función: se utiliza para obtener  el tipo de parámetro del tipo de función de adquisición.

type Props = Parameters<() => string> // []
    type Props1 = Parameters<(data: string) => void> // [string]
    type Props2 = Parameters<any>; // unknown[]
    type Props3 = Parameters<never>; // never

Fin

referencia:

  • Mecanografiado 4.0[2]

  • Comprensión profunda de TypeScript[3]

  • Una guía de estudio rara de TS (palabras de 1.8W)[4]

y varios recursos en Internet.

resumen

En este punto, el TSconocimiento relevante se ha terminado. Creo que tendrá TSuna comprensión más profunda después de dominar este conocimiento. Este artículo está clasificado de acuerdo con su propio entendimiento. Personalmente, creo que esta clasificación es más razonable. Si hay algo mejor Las sugerencias son bienvenidas para señalar en el área de comentarios ~

Cuando entré en contacto con él por primera vez TS, me resistí un poco, pero a medida que pasaba el tiempo, descubrí que TSes realmente fragante y TSno es demasiado difícil. Siempre que pases una cierta cantidad de tiempo, combinando y proyectándote, encontrarás la ley de la verdadera fragancia.

Supongo que te gusta

Origin blog.csdn.net/qq_34093387/article/details/127459704
Recomendado
Clasificación