Notas introductorias de TypeScript

desafío

  • Necesita comprender conceptos con los que los ingenieros de front-end pueden no estar familiarizados, como interfaces, genéricos, clases, enumeraciones, etc.
  • Puede aumentar algunos costos de desarrollo a corto plazo. Después de todo, es necesario escribir más definiciones de tipos. Sin embargo, para un proyecto que requiere mantenimiento a largo plazo, TypeScript puede reducir sus costos de mantenimiento.
  • La integración en el proceso de construcción requiere algo de trabajo
  • Puede que no sea perfecto en combinación con algunas bibliotecas

Instalar && compilar

npm install -g typescript
tsc hello.ts

Dirección de campo de TypeScript: https://www.typescriptlang.org/play/#De
hecho, new Boolean () devuelve un objeto booleano; llamar directamente a Boolean también puede devolver un tipo booleano :
defina el valor booleano correctamente:

let isDone: boolean = false;
let createdByBoolean: boolean = Boolean(1);

número define el tipo numérico:

let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
// ES6 中的二进制表示法
let binaryLiteral: number = 0b1010;
// ES6 中的八进制表示法
let octalLiteral: number = 0o744;
let notANumber: number = NaN;
let infinityNumber: number = Infinity;

Tipo de cuerda :

let myName: string = 'Tom';
let myAge: number = 25;

// 模板字符串
let sentence: string = `Hello, my name is ${
      
      myName}.
I'll be ${
      
      myAge + 1} years old next month.`;

JavaScript no tiene el concepto de void. En TypeScript, void se puede usar para representar una función sin ningún valor de retorno: es inútil
declarar una variable de tipo void , porque solo se puede asignar a undefined y null:

function alertName(): void {
    
    
    alert('My name is Tom');
}
let unusable: void = undefined;

En TypeScript, puede usar null e undefined para definir estos dos tipos de datos primitivos:
la diferencia con void es que undefined y null son subtipos de todos los tipos. Es decir, se pueden asignar variables de tipo indefinido a variables de tipo número:

let u: undefined = undefined;
let n: null = null;
// 这样不会报错
let num: number = undefined;
// 这样也不会报错
let u: undefined;
let num: number = u;

Si es un tipo común, no se permite cambiar el tipo durante el proceso de asignación:
pero si es de cualquier tipo , se permite asignarlo a cualquier tipo.
Se permite el acceso a cualquier propiedad y método sobre cualquier valor, incluso si no es un objeto; se
puede considerar que después de declarar una variable como cualquier valor, cualquier operación sobre ella, el tipo de contenido devuelto es cualquier valor.
Si una variable no especifica su tipo cuando se declara, se reconocerá como un tipo de valor arbitrario:

TypeScript inferirá un tipo cuando no se especifique un tipo explícito. Se trata de una inferencia de tipos .
Si no hay asignación en el momento de la definición, independientemente de si hay asignación posterior, se deducirá que es de cualquier tipo y no se verificará el tipo en absoluto:

let myFavoriteNumber = 'seven';
myFavoriteNumber = 7;

// index.ts(2,1): error TS2322: Type 'number' is not assignable to type 'string'.

Los tipos de unión utilizan | para separar cada tipo. El significado de let myFavoriteNumber: string | number es que el tipo de myFavoriteNumber puede ser cadena o número, pero no otros tipos.
Cuando TypeScript no está seguro de qué tipo es la variable de un tipo de unión, solo puede acceder a las propiedades o métodos comunes a todos los tipos del tipo de unión:

function getLength(something: string | number): number {
    
    
    return something.length;
}

// index.ts(2,22): error TS2339: Property 'length' does not exist on type 'string | number'.
//   Property 'length' does not exist on type 'number'.

Cuando se asigna una variable de un tipo de unión, se inferirá un tipo de acuerdo con las reglas de inferencia de tipos:

let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
console.log(myFavoriteNumber.length); // 5
myFavoriteNumber = 7;
console.log(myFavoriteNumber.length); // 编译时报错

// index.ts(5,30): error TS2339: Property 'length' does not exist on type 'number'.

La interfaz en TypeScript es un concepto muy flexible, además de abstraer parte del comportamiento de una clase, también se usa a menudo para describir la "forma de un objeto".

interface Person {
    
    
    name: string;
    age: number;
}

let tom: Person = {
    
    
    name: 'Tom',
    age: 25
};

En el ejemplo anterior, definimos una interfaz Person y luego definimos una variable tom cuyo tipo es Person. De esta manera, restringimos la forma de Tom para que sea consistente con la interfaz Person.
No se permite definir una variable que tenga menos atributos que la interfaz y tampoco se permite tener más atributos. Al asignar valores, la forma de la variable debe ser coherente con la forma de la interfaz.
A veces no queremos hacer coincidir una forma exactamente, por lo que podemos usar atributos opcionales . En este momento, todavía no está permitido agregar atributos indefinidos:

interface Person {
    
    
    name: string;
    age?: number;
}

let tom: Person = {
    
    
    name: 'Tom'
};

A veces queremos una interfaz que permita atributos arbitrarios , podemos usar los siguientes métodos:

interface Person {
    
    
    name: string;
    age?: number;
    [propName: string]: any;
}

let tom: Person = {
    
    
    name: 'Tom',
    gender: 'male'
};

Utilice [propName: string] para definir cualquier propiedad que tome el valor del tipo string.
Cabe señalar que una vez que se define cualquier atributo, el tipo del atributo determinado y el atributo opcional deben ser un subconjunto de su tipo.
Sólo se puede definir un atributo arbitrario en una interfaz. Si hay varios tipos de atributos en la interfaz, puede usar el tipo de unión en cualquier atributo.
Readonly define atributos de solo lectura:

interface Person {
    
    
    readonly id: number;
    name: string;
    age?: number;
    [propName: string]: any;
}

let tom: Person = {
    
    
    id: 89757,
    name: 'Tom',
    gender: 'male'
};

tom.id = 9527;

// index.ts(14,5): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property.

En el ejemplo anterior, después de que se inicializa el ID de atributo definido por readonly, se asigna nuevamente, por lo que se informa un error.
En TypeScript, hay muchas formas de definir el tipo de matriz , que es más flexible.

  • Notación "Tipo + corchetes "§
let fibonacci: number[] = [1, 1, 2, 3, 5];
  • Matriz de genéricos§
let fibonacci: Array<number> = [1, 1, 2, 3, 5];
  • Utilice interfaces para representar matrices§
interface NumberArray {
    
    
    [index: number]: number;
}
let fibonacci: NumberArray = [1, 1, 2, 3, 5];
  • Array-like § Los
    argumentos son en realidad una matriz, que no se puede describir de la misma manera que las matrices ordinarias, pero deben usar interfaces: en este ejemplo, además de restringir que cuando el tipo de índice es un número, el tipo de valor debe ser un número, que también lo restringe para tener dos atributos, longitud y destinatario. De hecho, las matrices de clases de uso común tienen sus propias definiciones de interfaz, como IArguments, NodeList, HTMLCollection, etc .:
function sum() {
    
    
    let args: {
    
    
        [index: number]: number;
        length: number;
        callee: Function;
    } = arguments;
}
function sum() {
    
    
    let args: IArguments = arguments;
}

Una función tiene entrada y salida. Para restringirla en TypeScript, se deben considerar tanto la entrada como la salida . La definición de tipo de la declaración de función es relativamente simple:
no se permite ingresar parámetros redundantes (o menos de los requeridos) de

function sum(x: number, y: number): number {
    
    
    return x + y;
}

Expresión de función

let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
    
    
    return x + y;
};

En la definición de tipo de TypeScript, => se usa para indicar la definición de una función. El lado izquierdo es el tipo de entrada, que debe estar entre paréntesis, y el lado derecho es el tipo de salida.

Puede utilizar la interfaz para definir la forma a la que debe adaptarse una función:

interface SearchFunc {
    
    
    (source: string, subString: string): boolean;
}

let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
    
    
    return source.search(subString) !== -1;
}

Utilice? Para indicar parámetros opcionales; debe tenerse en cuenta que los parámetros opcionales deben ir seguidos de los parámetros obligatorios. En otras palabras, no se permiten parámetros obligatorios después de los parámetros opcionales:

function buildName(firstName: string, lastName?: string) {
    
    
    if (lastName) {
    
    
        return firstName + ' ' + lastName;
    } else {
    
    
        return firstName;
    }
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');

En ES6, permitimos agregar valores predeterminados a los parámetros de la función. TypeScript reconocerá los parámetros con valores predeterminados como parámetros opcionales; en este momento, no está sujeto a la restricción de "los parámetros opcionales deben ir seguidos de parámetros requeridos ":

function buildName(firstName: string = 'Tom', lastName: string) {
    
    
    return firstName + ' ' + lastName;
}
let tomcat = buildName('Tom', 'Cat');
let cat = buildName(undefined, 'Cat');

El resto del parámetro solo puede ser el último parámetro:

function push(array: any[], ...items: any[]) {
    
    
    items.forEach(function(item) {
    
    
        array.push(item);
    });
}

let a = [];
push(a, 1, 2, 3);

Utilice la sobrecarga para definir varios tipos de funciones inversas:

function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
    
    
    if (typeof x === 'number') {
    
    
        return Number(x.toString().split('').reverse().join(''));
    } else if (typeof x === 'string') {
    
    
        return x.split('').reverse().join('');
    }
}

En el ejemplo anterior, hemos definido repetidamente la función inversa varias veces. Las primeras veces son definiciones de funciones y la última vez es la implementación de funciones. En la solicitud de código del editor, puede ver las dos primeras solicitudes correctamente.

Tenga en cuenta que TypeScript coincidirá primero con la primera definición de función, por lo que si varias definiciones de función tienen una relación de inclusión, primero debe escribir la definición precisa.
Type Assertion se puede utilizar para especificar manualmente el tipo de un valor. Sintaxis: valor como tipo o valor <tipo> El
primero debe usarse en la sintaxis tsx (la versión ts de la sintaxis jsx de React), es decir, el valor como tipo. La gramática de la forma es un ReactNode en tsx. Además de una aserción de tipo en ts, también puede representar un tipo genérico.
Por lo tanto, se recomienda que utilice el valor como sintaxis de tipo cuando utilice aserciones de tipo.
Utilice la afirmación de tipo para afirmar que un animal es un pez:

interface Cat {
    
    
    name: string;
    run(): void;
}
interface Fish {
    
    
    name: string;
    swim(): void;
}

function isFish(animal: Cat | Fish) {
    
    
    if (typeof (animal as Fish).swim === 'function') {
    
    
        return true;
    }
    return false;
}

Las afirmaciones de tipo solo pueden "engañar" al compilador de TypeScript y no pueden evitar errores de tiempo de ejecución. Por el contrario, el uso indebido de las afirmaciones de tipo puede provocar errores de tiempo de ejecución:

interface Cat {
    
    
    name: string;
    run(): void;
}
interface Fish {
    
    
    name: string;
    swim(): void;
}

function swim(animal: Cat | Fish) {
    
    
    (animal as Fish).swim();
}

const tom: Cat = {
    
    
    name: 'Tom',
    run() {
    
     console.log('run') }
};
swim(tom);
// Uncaught TypeError: animal.swim is not a function`

El ejemplo anterior no informará de un error al compilar, pero informará de un error en tiempo de ejecución: el motivo es (animal as Fish) .swim () Este código oculta la posibilidad de que el animal pueda ser Cat, y el animal se afirma directamente como Fish, y se compila TypeScript El procesador confía en nuestra afirmación, por lo que no hay ningún error de compilación al llamar a swim (). En resumen, debe tener mucho cuidado al usar aserciones de tipo y tratar de evitar llamar a métodos o hacer referencia a propiedades profundas después de la aserción para reducir errores innecesarios en tiempo de ejecución.

En algunos casos, ApiError y HttpError no son una clase real, sino solo una interfaz TypeScript (interfaz), una interfaz es un tipo, no un valor real, se eliminará en el resultado de la compilación, por supuesto, no puede usar instanceof para hazlo Juzgado en tiempo de ejecución:

interface ApiError extends Error {
    
    
    code: number;
}
interface HttpError extends Error {
    
    
    statusCode: number;
}

function isApiError(error: Error) {
    
    
    if (error instanceof ApiError) {
    
    
        return true;
    }
    return false;
}

// index.ts:9:26 - error TS2693: 'ApiError' only refers to a type, but is being used as a value here.

En este momento, solo puede usar la aserción de tipo para determinar si el parámetro pasado es ApiError al juzgar si el atributo de código existe:

interface ApiError extends Error {
    
    
    code: number;
}
interface HttpError extends Error {
    
    
    statusCode: number;
}

function isApiError(error: Error) {
    
    
    if (typeof (error as ApiError).code === 'number') {
    
    
        return true;
    }
    return false;
}
  • El tipo de unión se puede afirmar como uno de los tipos
  • La clase principal se puede afirmar como clase secundaria.
  • Cualquier tipo puede afirmarse como cualquier
  • Cualquiera se puede afirmar como cualquier tipo
  • Para permitir que A sea afirmado como B, solo A es compatible con B o B es compatible con A.
    De hecho, los primeros cuatro casos son casos especiales del último.
    La aserción de tipo no es una conversión de tipo, realmente no afectará el tipo de la variable.
interface Animal {
    
    
    name: string;
}
interface Cat {
    
    
    name: string;
    run(): void;
}

const animal: Animal = {
    
    
    name: 'tom'
};
let tom: Cat = animal;

// index.ts:12:5 - error TS2741: Property 'run' is missing in type 'Animal' but required in type 'Cat'.

No está permitido asignar animales a tom de tipo Cat.

Esto es fácil de entender. Animal puede considerarse como la clase padre de Cat. Por supuesto, no puede asignar una instancia de la clase padre a una variable cuyo tipo sea una subclase.

En profundidad, sus principales diferencias son:

Se afirma que el animal es Gato, y el
animal puede asignarse a Tom solo si Animal es compatible con Gato o
Gato es compatible con Animal. Sin embargo, Gato no es compatible con Animal.

Use declare var para definir el tipo

declare var jQuery: (selector: string) => any;

jQuery('#foo');

El archivo de declaración debe tener el sufijo .d.ts.

// src/jQuery.d.ts

declare var jQuery: (selector: string) => any;

En términos generales, ts analizará todos los archivos * .ts del proyecto, por supuesto, también incluye archivos que terminan en .d.ts. Entonces, cuando colocamos jQuery.d.ts en el proyecto, todos los demás archivos * .ts pueden obtener la definición de tipo de jQuery.
Archivo de declaración de terceros §Por
supuesto, el archivo de declaración jQuery no necesita ser definido por nosotros, la comunidad ya lo ha definido para nosotros: jQuery en DefinitelyTyped.

Podemos descargarlo y usarlo directamente, pero es más recomendable usar @types para administrar de manera uniforme los archivos de declaración de bibliotecas de terceros.

La forma de usar @types es muy simple, solo use npm para instalar el módulo de declaración correspondiente. Tome jQuery como ejemplo:

npm install @types/jquery --save-dev

Supongo que te gusta

Origin blog.csdn.net/taozi550185271/article/details/107630607
Recomendado
Clasificación