TypeScript se encuentra en una relación inusual con JavaScript. TypeScript ofrece todas las características de JavaScript, y una capa adicional sobre estas: el sistema de tipos de TypeScript.
Por ejemplo, JavaScript proporciona primitivas de lenguaje como string y number, pero no comprueba que las hayas asignado consistentemente. TypeScript sí lo hace.
Esto significa que tu código JavaScript existente que funciona también es código TypeScript. El principal beneficio de TypeScript es que puede resaltar comportamientos inesperados en tu código, disminuyendo la probabilidad de errores.
Este tutorial proporciona una breve descripción general de TypeScript, centrándose en su sistema de tipos.
Tipos por Inferencia
TypeScript conoce el lenguaje JavaScript y generará tipos para ti en muchos casos. Por ejemplo, al crear una variable y asignarle un valor particular, TypeScript usará el valor como su tipo.
tsTrylethelloWorld = "Hola Mundo";
Al comprender cómo funciona JavaScript, TypeScript puede construir un sistema de tipos que acepta código JavaScript pero tiene tipos. Esto ofrece un sistema de tipos sin necesidad de agregar caracteres adicionales para hacer explícitos los tipos en tu código. Así es como TypeScript sabe que helloWorld es un string en el ejemplo anterior.
Es posible que hayas escrito JavaScript en Visual Studio Code y hayas tenido autocompletado del editor. Visual Studio Code usa TypeScript internamente para facilitar el trabajo con JavaScript.
Definiendo Tipos
Puedes usar una amplia variedad de patrones de diseño en JavaScript. Sin embargo, algunos patrones de diseño dificultan la inferencia automática de tipos (por ejemplo, patrones que usan programación dinámica). Para cubrir estos casos, TypeScript admite una extensión del lenguaje JavaScript, que ofrece lugares para que le digas a TypeScript cuáles deberían ser los tipos.
Por ejemplo, para crear un objeto con un tipo inferido que incluya name: string e id: number, puedes escribir:
tsTryconstuser = {name : "Hayes",id : 0,};
Puedes describir explícitamente la forma de este objeto usando una declaración interface:
tsTryinterfaceUser {name : string;id : number;}
Luego puedes declarar que un objeto JavaScript se ajusta a la forma de tu nueva interface usando sintaxis como : TypeName después de la declaración de una variable:
tsTryconstuser :User = {name : "Hayes",id : 0,};
Si proporcionas un objeto que no coincide con la interfaz que has proporcionado, TypeScript te advertirá:
tsTryinterfaceUser {name : string;id : number;}constuser :User = {Object literal may only specify known properties, and 'username' does not exist in type 'User'.2353Object literal may only specify known properties, and 'username' does not exist in type 'User'.: "Hayes", // Error: La propiedad 'username' no existe en el tipo 'User'. 'name' falta. username id : 0,};
Dado que JavaScript admite clases y programación orientada a objetos, TypeScript también lo hace. Puedes usar una declaración de interfaz con clases:
tsTryinterfaceUser {name : string;id : number;}classUserAccount {name : string;id : number;constructor(name : string,id : number) {this.name =name ;this.id =id ;}}constuser :User = newUserAccount ("Murphy", 1);
Puedes usar interfaces para anotar parámetros y valores de retorno de funciones:
tsTryfunctiondeleteUser (user :User ) {// ...}functiongetAdminUser ():User {//...}
Ya existe un pequeño conjunto de tipos primitivos disponibles en JavaScript: boolean, bigint, null, number, string, symbol, y undefined, que puedes usar en una interfaz. TypeScript extiende esta lista con algunos más, como any (permite cualquier cosa), unknown (asegura que alguien que use este tipo declare cuál es el tipo), never (no es posible que este tipo ocurra), y void (una función que devuelve undefined o no tiene valor de retorno).
Verás que hay dos sintaxis para construir tipos: Interfaces y Tipos. Deberías preferir interface. Usa type cuando necesites características específicas.
Componiendo Tipos
Con TypeScript, puedes crear tipos complejos combinando tipos simples. Hay dos formas populares de hacerlo: uniones y genéricos.
Uniones
Con una unión, puedes declarar que un tipo podría ser uno de muchos tipos. Por ejemplo, puedes describir un tipo boolean como true o false:
tsTrytypeMyBool = true | false;
Nota: Si pasas el cursor sobre MyBool arriba, verás que se clasifica como boolean. Esa es una propiedad del Sistema de Tipos Estructural. Más sobre esto a continuación.
Un caso de uso popular para los tipos unión es describir el conjunto de literales de string o number literals que un valor puede ser:
tsTrytypeWindowStates = "open" | "closed" | "minimized";typeLockStates = "locked" | "unlocked";typePositiveOddNumbersUnderTen = 1 | 3 | 5 | 7 | 9;
Las uniones también proporcionan una forma de manejar diferentes tipos. Por ejemplo, puedes tener una función que tome un array o un string:
tsTryfunctiongetLength (obj : string | string[]) {returnobj .length ;}
Para conocer el tipo de una variable, usa typeof:
| Tipo | Predicado |
|---|---|
| string | typeof s === "string" |
| number | typeof n === "number" |
| boolean | typeof b === "boolean" |
| undefined | typeof undefined === "undefined" |
| function | typeof f === "function" |
| array | Array.isArray(a) |
Por ejemplo, puedes hacer que una función devuelva diferentes valores dependiendo de si se le pasa una cadena o un array:
tsTryfunctionwrapInArray (obj : string | string[]) {if (typeofobj === "string") {return [obj ];// ^? (parameter) obj: string}returnobj ;}
Genéricos
Los genéricos proporcionan variables a los tipos. Un ejemplo común es un array. Un array sin genéricos podría contener cualquier cosa. Un array con genéricos puede describir los valores que contiene el array.
tstype StringArray = Array<string>;type NumberArray = Array<number>;type ObjectWithNameArray = Array<{ name: string }>;
Puedes declarar tus propios tipos que usan genéricos:
tsTryinterfaceBackpack <Type > {add : (obj :Type ) => void;get : () =>Type ;}// Esta línea es un atajo para decirle a TypeScript que hay una// constante llamada `backpack`, y que no se preocupe de dónde vino.declare constbackpack :Backpack <string>;// object es un string, porque lo declaramos arriba como la parte variable de Backpack.constobject =backpack .get ();// Dado que la variable backpack es de tipo string, no puedes pasar un número a la función add.Argument of type 'number' is not assignable to parameter of type 'string'.2345Argument of type 'number' is not assignable to parameter of type 'string'.backpack .add (23 );
Sistema de Tipos Estructural
Uno de los principios fundamentales de TypeScript es que la verificación de tipos se centra en la forma que tienen los valores. Esto a veces se llama “tipado pato” (“duck typing”) o “tipado estructural”.
En un sistema de tipos estructural, si dos objetos tienen la misma forma, se consideran del mismo tipo.
tsTryinterfacePoint {x : number;y : number;}functionlogPoint (p :Point ) {console .log (`${p .x }, ${p .y }`);}// imprime "12, 26"constpoint = {x : 12,y : 26 };logPoint (point );
La variable point nunca se declara como de tipo Point. Sin embargo, TypeScript compara la forma de point con la forma de Point en la verificación de tipos. Tienen la misma forma, por lo que el código pasa.
La coincidencia de formas solo requiere que coincida un subconjunto de los campos del objeto.
tsTryconstpoint3 = {x : 12,y : 26,z : 89 };logPoint (point3 ); // imprime "12, 26"constrect = {x : 33,y : 3,width : 30,height : 80 };logPoint (rect ); // imprime "33, 3"constcolor = {hex : "#187ABF" };Argument of type '{ hex: string; }' is not assignable to parameter of type 'Point'. Type '{ hex: string; }' is missing the following properties from type 'Point': x, y2345Argument of type '{ hex: string; }' is not assignable to parameter of type 'Point'. Type '{ hex: string; }' is missing the following properties from type 'Point': x, ylogPoint (); color
No hay diferencia entre cómo las clases y los objetos se ajustan a las formas:
tsTryclassVirtualPoint {x : number;y : number;constructor(x : number,y : number) {this.x =x ;this.y =y ;}}constnewVPoint = newVirtualPoint (13, 56);logPoint (newVPoint ); // imprime "13, 56"
Si el objeto o la clase tienen todas las propiedades requeridas, TypeScript dirá que coinciden, independientemente de los detalles de implementación.
Próximos Pasos
Esto fue una breve descripción general de la sintaxis y las herramientas utilizadas en el código TypeScript cotidiano. Desde aquí, puedes:
- Leer el Manual completo de principio a fin
- Explorar los ejemplos del Playground