Skip to content

Instantly share code, notes, and snippets.

@fermmm
Created March 20, 2018 15:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fermmm/b1aa14911a0b5aa30f0884eeecaea27d to your computer and use it in GitHub Desktop.
Save fermmm/b1aa14911a0b5aa30f0884eeecaea27d to your computer and use it in GitHub Desktop.
TypeScript Machete
/////////////////////////////////////////////////// INSTALAR TYPESCRIPT EN UNA PC ////////////////////////////////////////////
npm install typescript -g
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////// INSTALAR TYPESCRIPT EN UN PROYECTO CON WEBPACK ////////////////////////////////////
/*
1) En el root del proyecto creamos un achivo llamado tsconfig.json con este contenido:
*/
{
"compileOnSave": false,
"compilerOptions": {
"noImplicitAny": true,
"allowJs": true,
"module": "ES6",
"target": "es5",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": [ "es2015", "dom" ],
"moduleResolution": "node",
"sourceMap": true,
"suppressImplicitAnyIndexErrors": true,
"jsx": "react"
}
}
/*
2) En el archvo webpack.config.js dentro de module.rules tiene que estar esto:
*/
module: {
rules: [
...
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}
/*
3) En el mismo archvo (webpack.config.js) dentro de resolve.extensions tiene que estar '.tsx' y '.ts':
*/
resolve: {
extensions: [ '.tsx', '.ts', '.js' ]
},
/*
4) Ejecutar el siguiente comando:
npm install ts-loader typescript
*/
/*
Con eso ya tendría que funcionar Typescript.
*/
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////// TIPOS BASICOS /////////////////////////////////////////////////////////////////////////
///////// Declaración:
string
number
boolean
Array<TIPO_DEL_CONTENIDO> o tambien: TIPO_DEL_CONTENIDO[]
void // Se usa solo para indicar que una funcion no devuelve nada, en realidad no califica como un tipo pero se usa de la misma manera.
(a:string, b:string)=>void // El tipo de una funcion, es largo de escribir pero contiene informacion muy util.
CLASE // Para una clase el tipo es el nombre de la clase, lo mismo para la interfaz o enum.
any // NO HAY QUE USARLO, si sentis que es la unica solucion a un problema es por que algo esta mal. Este tipo solo sirve para desactivar el tipado para el elemento.
object // NO HAY QUE USARLO, sirve para los objetos que se escriben con {}, igual que el any es un tipo sin informacion por lo tanto es inservible y anti-tipado.
//////// Uso:
/*
Los tipos se escriben al crear una variable o una funcion, por ejemplo:
*/
var miVariable : string = "hola";
function generarSaludo(nombre : string):string
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////// EJEMPLOS DE USO Y VARIANTES //////////////////////////////////////////////////////////////////
export class Employee implements ISarasa
{
private department : string | number; // Una propiedad puede contener mas de un tipo a la vez separado por | , esto se llama: "Union Types".
public _list : string[]; // Los arrays son tipados, solo pueden contener elementos del tipo indicado
public list2 : Array<string>; // Otra sintaxis para el tipo array que evita errores de sintaxis aveces.
public myEvent : (x: number, y: number) => void; // Function types
private dictionary : Map<Array<string> , string> = new Map([ // Diccionario
[["test"], "1"],
[["test2"], "2"],
]);
constructor(yourName: string, department: string | number) // En el constructor no se escribe que tipo devuelve por que es obvio.
{
this.department = department;
}
public getElevatorPitch(): string
{
return `Hello, my name is ${this.name} and I work in ${this.department}.`;
}
/*
Getter setters:
*/
get superList(): Array<string>
{
return this._list;
}
set superList(newList: Array<string>) : void
{
this._list = newList;
}
////////////// Como checkear los union types y asi poder usarlos:
public unionTypesUsageExample(param: string | number | HTMLElement | HTMLImageElement | HTMLDivElement): void
{
// Se usa typeof para los tipos basicos (string y number) y se usa instanceof para los demas tipos:
if (param instanceof HTMLDivElement) {
console.log('this is HTMLDivElement');
} else if (param instanceof HTMLImageElement) {
console.log('this is HTMLImageElement');
} else if (param instanceof HTMLElement) {
console.log('this is HTMLElement');
} else if (typeof param === "string") {
console.log('this is string');
} else if (typeof param === "number") {
console.log('this is number');
} else {
console.log("You're not supposed to be here!");
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////// CAST ////////////////////////////////////////////////////////////////
/*
Se le llama castear cuando se quiere hacer pasar un tipo por otro, si son compatibles nos los va a permitir, los tipos compatibles en
general son las clases padres con sus clases hijos.
Se puede castear con 2 sintaxis, una sirve para cuando la otra tira error de sintaxis por culpa del contexto o para cuando se quiere
dejar mas legible el codigo, funcionalmente son identicas en TS.
*/
///////// Sintaxis 1
hacerAlgo((ClaseHijo)instanciaClasePadre);
///////// Sintaxis 2
instanciaClaseHijo as ClasePadre
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// MODIFICADORES DE ACCESO //////////////////////////////////////////////////////////////////
/*
Nos permite hacer que una clase tenga una especie de api publica y privada para que no se haga autocompletado de cosas que no hay que ejecutar.
*/
export class Person
{
private id : number; // private hace que la propiedad solo sea visible dentro de la clase
protected name : string; // protected hace que la propiedad sea solo visible dentro de la clase y clases hijas
public nickname : string // public deja que la propiedad sea visible desde afuera como es comun en JS, tambien es
// la default si no se escribe el modificador de acceso.
// Los modificadores de acceso en los parametros del constructor crean parametros y propiedades a la vez
constructor(private lastName: string, name: string)
{
this.name = name; // Usando un modificador de acceso en la propiedad del constructor nos ahorramos este tipo de lineas.
}
private saludar():void // Tambien se usan en los metodos.
{
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////// INTERFACES /////////////////////////////////////////////////////////////////////////
/*
Describen el contenido de un objeto, tambien obligan a una clase o a un objeto a implementar elementos (de lo contrario tira error), de esa
manera que el contenido es previsible en tiempo de escritura de codigo para que la IDE pueda ayudarte, tambien compatibiliza elementos que
utilizan la misma interfaz.
No ocupan nada en el proyecto por que se borra de la compilacion.
*/
/////////////////// Declarar:
export interface IExample // Las interfaces se recomienda escribirlas con una I adelante del nombre.
{
name: string; // Ejemplo de propiedad obligatoria
color?: string; // Ejemplo de propiedad opcional (es con el signo de interrogación)
getElevatorPitch(): string; // Ejemplo de metodo obligatorio.
returnAnyFuckingShit?(): number; // Ejemplo de metodo opcional.
}
/////////////////// Utilizar en una clase:
class MiClase implements IExample
/////////////////// Utilizar en un objeto:
<IExample>{name:"pedro", color:"red"}
/*
En esa ultima linea nos tiraria error por que no tenemos agregada una funcion llamada getElevatorPitch en el objeto.
No hace falta que las clases tengan una interfaz, pero si todos los objetos creados utilizando {}, deberian tener una interfaz.
*/
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////// ENUMS ////////////////////////////////////////////////////////////////
/*
Se usan por ejemplo cuando una variable puede tener 3 estados y no podemos usar un boolean por que solo tiene 2. Este problema se puede
solucionar usando number o string pero nos deja un codigo que si alguien lo lee no sabe que poner exactamente en esa variable a menos que
lea una documentacion que puede no existir o ser de mala calidad. Para solucionar ese problema existen los enums.
*/
/////// Declaración:
export enum Direction {
Up,
Down,
Left,
Right,
}
/////// Uso:
setDirection(Direction.Left);
function setDirection(newDirection:Direction)
{
if(newDirection == Direction.Left)
console.log("going left");
}
/////// Obtener el nombre de un elemento como string:
const upName:string = (string)Direction.Up; // Nos guarda: "Up". Esto es especialmente util al armar un JSON
/*
El transpilador transforma los usos del enum en numeros, se puede especificar que numeros queremos para cada elemento
del enum (es raro que sea necesario especificarlo):
enum Direction {
Up = 0,
Down = 1,
Left = 2,
Right = 3
}
También se pueden hacer "string enums":
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT",
}
*/
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////// GENERICS //////////////////////////////////////////////////////////////
/*
Es para que nunca sea necesario usar los tipos "any" u "object", caundo si o si necesitas esos tipos es por que tenes que recurrir a esto.
Permite crear metodos o clases donde no hace falta especificar el tipo, pero se lo pasa por otro lado para no perderlo.
*/
///// Declaración:
function randomizeArray<T>(array: Array<T>): Array<T>
{
...
}
///// Uso:
const randomized:Array<string> = randomizeArray<string>(myArray);
/*
Si no usaramos esto, el método habría que escribirlo asi:
function randomizeArray(array: Array<any>): Array<any>
Perderiamos la informacion del tipo al almacenar lo que el metodo devuelve, ya que "any" no contiene ninguna información.
*/
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////// USAR UNA LIBRERIA NO TIPADA /////////////////////////////////////////////////////
/*
Se pueden usar librerias hechas en JS como si estuvieran hechas en TS, la comunidad escribe archivos
con extensión .d.ts que son definiciones de tipos para librerias de JS, hay muchas escritas y se encuentra de todo.
En otras palabras le agrega los tipos a una libreria que no los tiene.
Para agregarle los tipos a una libreria hacemos lo siguiente:
1) (Opcional) Verificamos si la comunidad hizo los archivos .d.ts de la librería que queremos, usando este buscador:
https://microsoft.github.io/TypeSearch/
2) Si no la encontraste ahí podemos usar la libreria sin los tipos, ver instrucciones para eso.
Si la encontraste tambien estan las instrucciones de como instalarlo, en general es siempre lo mismo:
npm install agregandole el prefijo @types/ por ejemplo:
npm install @types/react
De esa manera si ya sabemos que los tipos existen, nisiqueira hace falta buscarlos en la pagina, con ese
comando instalamos los tipos igual que se instala un paquete cualquiera, cualquier cosa saldrá un error.
Importante saber esto: No importa la ubicación de los archivos .d.ts, el proceso de typescript busca todos
estos archivos en el proyecto no importa donde esten, estos archivos no pesan en la compilación final del JS por
que son ignorados.
*/
/*
Esta herramienta instala automaticamente los tipos en un proyecto ya empezado basado en las librerias que usa:
https://github.com/jeffijoe/typesync
*/
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////// CUANDO NO TENEMOS LOS TIPOS DE UNA LIBRERIA EN JS ////////////////////////////////////////////////
/*
El proceso para crear una definicion de tipos .d.ts es bastante automatizado, no requiere mucho tiempo, mas detalles en este link:
https://stackoverflow.com/questions/12687779/how-do-you-produce-a-d-ts-typings-definition-file-from-an-existing-javascript
Pero si se esta muy mal de tiempo y se quiere salir del paso, se puede hacer una declaracion de tipos utilizando el tipo any para la clase
principal y asi todo lo que esta adentro queda con los tipos desactivados y no nos tira ningun error. Esto se hace de la siguiente manera:
*/
// Para usar una clase de JS:
declare class LaClaseDeJs { constructor(...args: any[]); };
// Para usar una variable global escrita en JS:
declare var miVariableNoTipadaDeJs: any;
// Para usar cualquier variable global inyectada usando prototype, como pasa con los plugins de jQuery:
declare global {interface JQuery {metodoDelPlugin(...args: any[]): JQuery;}}
/*
Esto va en un archivo .d.ts pero tambien se puede poner arriba de todo en el archivo de typescript donde vamos a usar la libreria en JS, antes
o despues de los import. La palabra declare es similar a interface, lo que hace es crear tipos y nada mas, el codigo se borra al compilar.
*/
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////// CONVERTIR JSON EN UNA INTERFAZ /////////////////////////////////////////////////
/*
Hay aplicaciones web para convertir el texto de un JSON en una interfaz de TypeScript, el mejor al dia de la fecha es este:
https://jvilk.com/MakeTypes/
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment