{"id":20021470,"url":"https://github.com/dieg0code/tsc_basics","last_synced_at":"2025-03-02T03:42:31.794Z","repository":{"id":188197542,"uuid":"391850320","full_name":"Dieg0Code/TSC_basics","owner":"Dieg0Code","description":"Intro a Typescript","archived":false,"fork":false,"pushed_at":"2021-10-21T21:52:38.000Z","size":687,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-12T16:24:54.890Z","etag":null,"topics":["basics","learning","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Dieg0Code.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2021-08-02T07:16:29.000Z","updated_at":"2024-05-20T11:11:05.000Z","dependencies_parsed_at":"2023-08-14T08:37:01.517Z","dependency_job_id":null,"html_url":"https://github.com/Dieg0Code/TSC_basics","commit_stats":null,"previous_names":["dieg0code/tsc_basics"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dieg0Code%2FTSC_basics","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dieg0Code%2FTSC_basics/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dieg0Code%2FTSC_basics/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dieg0Code%2FTSC_basics/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Dieg0Code","download_url":"https://codeload.github.com/Dieg0Code/TSC_basics/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241455377,"owners_count":19965602,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["basics","learning","typescript"],"created_at":"2024-11-13T08:36:52.501Z","updated_at":"2025-03-02T03:42:31.767Z","avatar_url":"https://github.com/Dieg0Code.png","language":"TypeScript","readme":"# Typescript\n\n![TS Logo](https://upload.wikimedia.org/wikipedia/commons/thumb/4/4c/Typescript_logo_2020.svg/512px-Typescript_logo_2020.svg.png)\n\n## ¿Qué es Typescript?\n\nEs un superconjunto tipado de JavaScript que permite la creación de programas que se pueden compilar a JavaScript.\n\n- **Lenguajes de programación tipado**: Posee un conjunto de tipos de datos que definen el comportamiento de las variables y funciones. Pudiendo personalizarlo o extenderlo.\n- **Lenguajes de alto nivel**: Entendible por humanos y posee un alto nivel de abstracción del código maquina.\n- **Genera como resultado código JavaScript**: Genera código JavaScript que puede ser ejecutado en navegadores web.\n- **Es de código abierto**: Puede ser modificado y extendido por cualquier persona.\n- **Multiplataforma**: Puede ser ejecutado en múltiples plataformas: Windows, Mac, Linux, etc.\n\n## ¿Por qué utilizar Typescript?\n\n- Programación orientada a objetos.\n- Potenciar tu código javascript.\n- Mayor productividad.\n- Poderoso sistema de tipos.\n- Compila a ES5, ES6 y más.\n- Proyecto muy activo / Open Source.\n- Actualizaciones constantes.\n- Comunidad creciente.\n- Puede prevenir cerca del 15% de bugs.\n- Puede usarse en el back-end y front-end.\n\n## ¿Cómo instalar Typescript?\n\nPara instalar Typescript, necesitas tener instalado el paquete de NodeJS. Luego, ejecuta el siguiente comando:\n\n```bash\nnpm install -g typescript\n```\n\nUna vez instalado, puedes verificar la version de Typescript que estás usando con el siguiente comando:\n\n``` bash\ntsc -v\n```\n\nLos archivos que puede compilar typescript son los que tienen la extensión `.ts`, el compilador lo que hace es convertir el código typescript en código javascript, luego de verificar que el código escrito es correcto. Generaría un archivo con el mismo nombre que el archivo de origen pero con la extensión `.js`.\n\n```bash\ntsc file.ts\n```\n\nComo resultado, se generará un archivo `file.js`. Es en este punto en donde se necesita un javascript runtime para que interprete el código javascript generado.\n\n```bash\nnode file.js\n```\n\n### Compilar de manera automática nuestros ficheros .ts\n\n```bash\ntsc -w file.ts\n```\n\nEste comando lo que hace es vigilar los cambios y generar un archivo `file.js` cada vez que se modifique el código.\n\n## El archivo `tsconfig.json`\n\nEs un archivo que contiene configuraciones para el compilador.\n\n- Especifica la raíz del proyecto typescript.\n- Permite configurar las opciones de compilación.\n\n### Generación del archivo `tsconfig.json`\n\n```bash\ntsc --init\n```\n\nEste comando genera un archivo `tsconfig.json` en el directorio actual.\n\nEste archivo es el que se usa para configurar el compilador.\n\nEjemplo:\n\n```json\n{\n    \"compilerOptions\": {\n        \"target\": \"es5\",\n        \"module\": \"commonjs\",\n        \"strict\": true,\n        \"removeComments\": true,\n    }\n}\n```\n\nSe trata de un archivo json literal con un atributo llamado `compilerOptions` que nos permite configurar las opciones de compilación.\n\nPor ejemplo podemos utilizar el parámetro `target` para especificar la versión de la ECMAScript que se va a generar como resultado de la compilación, puede ser `es3`, `es5`, `es6`, etc. Dependiendo de los objetivos que tenemos en nuestro proyecto.\n\nAsi mismo podemos especificar un atributo llamado `module` en donde vamos a especificar la configuración para generación de módulos en nuestro proyecto typescript. Entre los valores que podemos usar están: `commonjs`, `amd`, `system`, `umd`, `none`, entre otros.\n\nTambién podemos especificar un atributo llamado `strict` que recibe un valor booleano que indica si se va a compilar el código en modo estricto, es decir, si se va a compilar el código verificando que todos los tipos de datos son correctos.\n\nFinalmente podemos especificar un atributo llamado `removeComments` que recibe un valor booleano que indica si se va a eliminar los comentarios de nuestro código.\n\nTambién podemos especificar opciones adicionales que vayan de la mano con la configuración de nuestro proyecto.\n\n```json\n// tsconfig.json\n{\n    \"extends\": \"./configs/base\",\n    \"compileOnSave\": true,\n    \"compilerOptions\": {\n        \"target\": \"es5\",\n        \"module\": \"commonjs\",\n        \"strict\": true,\n        \"removeComments\": true,\n    },\n    \"include\": [\n        \"src/**/*.ts\"\n    ],\n    \"exclude\": [\n        \"node_modules\"\n        \"**/*.test.ts\"\n    ]\n}\n```\n\nDe esta forma usamos el parámetro `include` que llega a ser una lista de declaraciones de tipo que se van a incluir en el proceso de compilación. Lo cual significa que podemos mencionar que directorios y subdirectorios se van a incluir en el proceso de compilación.\n\nAsí mismo podemos especificar una sección equivalente pero para excluir directorios y archivos del proceso de compilación. Podemos especificar por ejemplo la carpeta de `node_modules` para que no se tomen en cuenta en el proceso de compilación.\n\nFinalmente podemos mencionar también en el archivo de configuración la herencia de compilaciones, podemos definir un archivo `tsconfig.json` general para nuestro proyecto y heredar las configuraciones usando el parámetro `extends`. De la misma forma, si es que estamos usando algún editor de código o IDE podemos usar el parámetro `compileOnSave` para indicar que el compilador se ejecute cada vez que se guarde un archivo.\n\n## Usando el archivo `tsconfig.json`\n\nUna vez que hayamos generado y configurado el archivo `tsconfig.json`, ¿de qué forma podemos usarlo?.\n\n```bash\ntsc # typescript empieza a buscar el archivo tsconfig.json en el directorio actual para tomar en cuenta dichos parámetros de configuración.\n```\n\nTambién podemos usar el parámetro `--project` para indicar el directorio donde se encuentra el archivo `tsconfig.json`\n\n```bash\ntsc --project tscBasics\n```\n\nEn caso de que queramos omitir el uso de `tsconfig.json` podemos simplemente compilar un archivo de tipo `.ts` directamente.\n\n```bash\ntsc file.ts\n```\n\n## Tipado en TypeScript\n\nEn typescript podemos definir variables de manera explícita, eso significa que debemos tomar en cuenta el tipo de dato que va a tener la variable. Pero también typescript tiene la capacidad de inferir el tipo de dato de una variable, es decir, si no se especifica el tipo de dato de la variable, typescript lo infiere.\n\n### Tipado Explícito\n\n```typescript\nlet a: number = 5;\n```\n\n`nombreVariable` `:` `tipoVariable`\n\n### Tipado Implícito\n\n```typescript\nlet a = 5;\n```\n\nTypescript infiere el tipo de dato de `a` como `number`. La variable debe estar inicializada para que el tipo de dato pueda ser inferido.\n\n### Tipos primitivos\n\n- `number` : Valores numéricos, hexadecimales, binarios, octales.\n\n```typescript\n// Number\n// explicito\n\nlet phone: number;\nphone = 1;\nphone = 5678903;\n\n// phone = 'hola'; // Error\n\n// Inferido\nlet phoneNumber = 567890;\nphoneNumber = 123;\n// phoneNumber = true; // Error\n\nlet hex: number = 0xf00d;\nlet binary: number = 0b1010;\nlet octal: number = 0o744;\n```\n\n- `boolean` : El tipo de dato más simple en typescript. Dos valores posibles: `true` o `false`.\n\n```typescript\n// Boolean\n// explicito\nlet isAdmin: boolean;\nisAdmin = true;\nisAdmin = false;\n\n// Inferido\nlet isAdmin = true;\nisAdmin = false;\nisAdmin = 'true'; // Error\n```\n\n- `string` : El tipo de dato para trabajar con dato textuales o cadenas de caracteres. Así como en javascript, se pueden usar comillas dobles (\"\") y simples ('') para definir cadenas de caracteres.\n\n```typescript\n// String\n// explicito\nlet name: string;\nname = 'Juan';\nname = 'Juan Pérez';\n\n// Inferido\nlet name = 'Juan';\nname = 'Juan Pérez';\nname = 123; // Error\n```\n\n- `template string` : Permite definir múltiples líneas de texto. Pueden contener expresiones o variables embebidas. Se debe usar el carácter backtick/backquote (\\`) y para expresiones `${expr}`.\n\n```typescript\n// Template String\nlet userName = 'Pepe';\nlet firstName = 'Juan';\nlet phone = '1234567890';\nlet isAdmin = true;\n\nlet userInfo = `\n    User info: \n    username: ${username}\n    first name: ${firstName + ' Pérez'}\n    phone: ${phone}\n    isAdmin: ${isAdmin}\n`;\nconsole.log('userInfo', userInfo);\n```\n\n- `array` : Al igual que en javascript, typescript permite definir arrays que contienen un conjunto de valores. Usa dos notaciones: `[]` y `Array\u003ctipo\u003e`\n\n```typescript\n// Array\n// explicito\nlet numbers: number[] = [];\nnumbers = [1, 2, 3];\nnumbers = [1, '2', 3]; // Error\n\n// Inferido\nlet otherNumbers = [1, 2, 3]; // number[]\nlet otherNumbers = [1, '2', 3]; // Error\n\n// Array\u003ctipo\u003e\nlet pictureTitles: Array\u003cstring\u003e; // string[]\npictureTitles = ['A', 'B', 'C'];\n\n// Accediendo a los valores en un array\nconsole.log('first number', numbers[0]);\nconsole.log('first title', pictureTitles[0]);\n\n// Propiedades en arrays\nconsole.log('length', pictureTitles.length);\n\n// Uso de funciones en arrays\nnumbers.push(4); // Agrega el valor 4 al final del array\npictureTitles.sort(); // Ordena los valores del array en este caso de forma alfabética\n```\n\n- `tuple` : Una tupla en typescript es un array de elementos que están tipados. De esta manera cada vez que haya que insertar un elemento se validará que dicho elemento coincida con el tipo de dato establecido en la tupla. Las tuplas permiten expresar un array con un número específico de elementos.\n\n```typescript\n// Tuple\n// [1, 'user']\nlet user: [number, string];\nuser = [1, 'Juan'];\n\nconsole.log('user', user);\nconsole.log('username', user[1]);\nconsole.log('user name length', user[1].length); // esto no funciona con otro tipo de dato que no sean strings\nconsole.log('user id', user[0]); // aquí no funcionaria pedir el length\n\n// tuplas con varios valores\n// id, userName, isPro\nlet userInfo: [number, string, boolean];\nuserInfo = [2, 'Pedro', true];\nconsole.log('userInfo', userInfo);\n\n// array de tuplas\nlet array: [number, string][] = []; // debe ser inicializada para poder usar propiedades como push\narray.push([1, 'Juan']); // 0\narray.push([2, 'Pedro']); // 1\narray.push([3, 'Antonio']); // 2\n\n// Uso de funciones en arrays\n// Antonio -\u003e Antonio001\n\narray[2][1] = array[2][1].concat('001'); // Antonio001\nconsole.log('array', array);\n```\n\n- `enum` : Los enumerados permiten definir un conjunto de constantes con nombre. Tiene la ventaja de adaptarse al contexto de la aplicación.\n\n```typescript\n// Enum\n// Orientación para fotografiás\n// const landscape = 0;\n// const portrait = 1;\n// const square = 2;\n// const panorama = 3;\n\nenum PhotoOrientation {\n    Landscape = 0, // 0\n    Portrait = 1, // 1\n    Square = 2, // 2\n    Panorama = 3 // 3\n}\n\nconst landscape: PhotoOrientation = PhotoOrientation.Landscape;\nconsole.log('landscape', landscape); // landscape 0\nconsole.log('landscape', PhotoOrientation[landscape]);\n\nenum PictureOrientation {\n    Landscape = 10, // 10\n    Portrait, // 11\n    Square, // 12\n    Panorama // 13\n}\n\n// Siempre son valores consecutivos que se van incrementando de 1 en 1\n\nconsole.log('portrait', PictureOrientation.Portrait); // portrait 11\n\nenum Country {\n    Bolivia = 'bol',\n    Colombia = 'col',\n    México = 'mex',\n    EEUU = 'usa',\n    España = 'esp'\n}\n\nconst country: Country = Country.Bolivia;\nconsole.log('country', country); // country bol\n```\n\n- `any` : Usado para capturar valores dinámicos. Los valores pueden cambiar de tipo dependiendo del contexto. APIs externas, librerías de terceros, etc.\n\nEn la practica `any` debe ser usado como último recurso, esperaríamos aplicarlo en caso de que no sepamos el tipo de la variable a priori.\n\n```typescript\n// any\n// explicito\nlet idUser: any;\nidUser = 1; // Tipo: number\nidUser = '1'; // Tipo: string\nconsole.log('idUser', idUser);\n\n// Inferido\nlet otherIdUser;\notherIdUser = 1;\notherIdUser = '1';\nconsole.log('otherIdUser', otherIdUser);\n\nlet surprise: any = 'hello typescript';\n// surprise.sayHello(); // Error\nconst res = surprise.substring(6); // Error\nconsole.log('res', res);\n```\n\n- `void` : Void es lo opuesto a any. Representa la ausencia de tipo. Comúnmente se usa como tipo de retorno de funciones.\n\n```typescript\n// void\n// explicito\nfunction showInfo(user: any): void {\n    console.log('user info', user.id, user.userName, user.firstName);\n}\n\nshowInfo({ id: 1, userName: 'Pepe', firstName: 'Juan' });\n\n// Inferido\nfunction showFormatedInfo(user: any) {\n    console.log('User info', `\n        id: ${user.id}\n        userName: ${user.userName}\n        firstName: ${user.firstName}\n    `);\n}\n\nshowFormatedInfo({ id: 1, userName: 'Pepe', firstName: 'Juan' });\n```\n\nUna variable de tipo `void` no puede ser inicializada, se puede asignar unicamente como `null` o `undefined` como valores.\n\n```typescript\n// tipo void, como tipo de dato en variable\nlet unusable: void;\nunusable = null;\nunusable = undefined;\n```\n\nNormalmente esto nos daría un error puesto que en nuestro archivo de configuración tenemos el modo `strict` en nuestro chequeo de tipos.\n\nEsto no es recomendable, pero es posible. Nos sirve para entender que `null` y `undefined` son una especie de subtipo de `void`.\n\n- `null`: En Typescript, ambos valores `null` y `undefined` tienen sus respectivos tipos.\n- `undefined`\n\n```typescript\n// null y undefined\n// explicito\nlet nullValue: null;\nnullValue = null;\nnullValue = 1; // Error\n\nlet otherVariable = null; // lo infiere como any\notherVariable = 'test'; // se puede porque el tipo de variable es any\n\nconsole.log('nullValue', nullValue);\nconsole.log('otherVariable', otherVariable);\n\n// undefined\nlet undefinedValue: undefined = undefined;\nundefinedValue = 'test'; // Error\n\nlet otherUndefinedValue = undefined; // lo infiere como any\n\nconsole.log('undefinedValue', undefinedValue);\nconsole.log('otherUndefinedValue', otherUndefinedValue);\n```\n\n`null` y `undefined` se pueden asumir como subtipos de los otros tipos de datos. Significa que podemos asignar `null` y `undefined` a variables de tipo `number` o `string`, por ejemplo.\n\n```typescript\n// null y undefined como subtipos\n\n// --strictNullChecks\nlet albumName: string;\n// albumName = null; // Error\n// albumName = undefined; // Error\n```\n\nUna de las maneras más prácticas de solucionar problemas habituales cuando trabajamos con código javaScript consiste en evitar la asignación de valores `null` y `undefined` a variables. Typescript provee los mecanismos necesarios para evitar esto, una de las formas consiste en utilizar el parámetro `strictNullChecks` en la configuración del archivo de configuración, con lo cual el compilador verifica que no se está asignando un valor `null` o `undefined` a una variable.\n\nTambién podemos usar el parámetro `strictNullChecks` mediante la linea de comandos.\n\n```bash\ntsc file.ts --strictNullChecks\n```\n\nNos devuelve un reporte de todas las lineas en las que se encontró una asignación de valor `null` o `undefined` a una variable.\n\nEsto se hace porque cuando se asignan valores `null` o `undefined` a variables el código se vuelve propenso a producir errores.\n\n- `never` : Representa el tipo de valor que nunca ocurre. Se usa en funciones que lanzan excepciones o en funciones que nunca retornan un valor.\n\n```typescript\n// never\n// explicito\nfunction handleError(code: number, message: string): never {\n    // process your code\n    // generate a message\n    throw new Error(`${message}. Code: ${code}`);\n}\n\ntry {\n    handleError(404, 'Not found');\n} catch (error) {\n}\n\nfunction sumNumbers(limit: number): never {\n    let sum = 0;\n    // infinit loop\n    while (true){\n        sum++;\n    }\n    // return sum;\n}\n\nsumNumbers(10); // never return sum, bc of infinit loop\n```\n\n- `object` : Es el tipo de dato que representa un valor no primitivo. Es el tipo para variable que no sea `number`, `string`, `boolean`, `undefined`, `null`, etc.\n\n```typescript\n// object\n// explicito\nlet user: object;\nuser = {}; // Object\n\nuser = {\n    id: 1,\n    userName: 'Pepe',\n    firstName: 'Juan',\n    isPro: true\n};\n\nconsole.log('user', user);\n// Object vs object(Clase JS vs tipo TS)\nconst myObj = { // inferido como clase es decir tipo Object\n    id: 1,\n    userName: 'Pepe',\n    firstName: 'Juan',\n    isPro: true\n};\n\nconst isInstance = myObj instanceof Object; // true\n\nconsole.log('user.userName', myObj.userName);\n\n// console.log('user.userName', user.userName); // Error property 'userName' does not exist on type 'object'.\n```\n\n#### `Object` vs `object`\n\n- `Object` : Instancia de la clase `Object` de javascript.\n- `object` : Tipo para valores no primitivos. Con este tipo no se puede acceder a las propiedades del objeto.\n\nEn resumen, la principal diferencia entre `Object` y `object` es que `Object` es una clase de javascript, mientras que `object` es un tipo de dato.\n\n## Union de Tipos, Alias y Tipos Literales\n\n### Union de Tipos\n\n- En `Typescript` se puede definir una variable con múltiples tipos de datos: *Union Type*.\n- Se usa el símbolo de pipe `|` entre tipos.\n\n```typescript\n// union type\n// 10, '10'\nlet idUser: number | string;\nidUser = 10;\nidUser = '10';\n\n// Buscar username dado un id\nfunction getUsername(id: number | string) {\n    // Lógica de negocio, find the user\n    return 'Pepe';\n}\n\ngetUsername(10); // 'Pepe'\ngetUsername('10'); // 'Pepe'\n```\n\n### Alias de Tipos\n\n- Typescript permite crear un alias como nuevo nombre para un tipo.\n- El alias se puede aplicar también a un conjunto o combinación de tipos.\n- Se usa la palabra reservada `type` para crear alias.\n\n```typescript\n// alias\n// nos ayudan a evitar la redundancia en la union de tipos\ntype IdUser = number | string;\ntype UserName = string; // alias para el tipo string\nlet idUser: IdUser;\n\nfunction getUsername(idUser: IdUser): UserName {\n    // Lógica de negocio, find the user\n    return 'Pepe';\n}\n\ngetUsername(10); // 'Pepe'\ngetUsername('10'); // 'Pepe'\n```\n\n### Tipos Literales\n\n- Una variable con un tipo literal pude contener únicamente una cadena de conjunto.\n- Se usan cadenas como \"tipos\", combinados con el símbolo de pipe `|` entre ellos.\n\n```typescript\n// Tipos Literales\n// 100x100, 500x500, 1000x1000\ntype SquareSizes = '100x100' | '500x500' | '1000x1000';\nlet smallPicture: SquareSizes = '100x100';\n// let smallPicture: SquareSizes = '200x200'; // Error\nlet mediumPicture: SquareSizes = '500x500';\n```\n\n## Aserciones de tipos\n\nAdemas de los tipos de datos, Typescript también provee un mecanismo para poder convertir estos tipos.\n\n- Cuando el programador conoce más que Typescript sobre el valor de una variable se hace necesario utilizar algún tipo de operador que me permita hacer una converción de tipos de datos.\n- Se parece al casting de tipos en otros lenguajes de programación. Sin embargo no es lo mismo puesto que Typescript no realiza ningún tipo de verificación y no afecta al tiempo de ejecución de la aplicación.\n- Usa dos sintaxis: `\u003cAngle Bracket\u003e` y `(variable as tipo)`\n\n```typescript\n// Aserciones de tipos\n// \u003ctipo\u003e Angle Bracket syntax\nlet userName: any;\nuserName = 'Pepe';\n\n// tenemos una cadena, TS confía en mi!\nlet message: string = (\u003cstring\u003euserName).length \u003e 5 ? ` Welcome ${userName}`: 'Username is too short';\nconsole.log('message', message);\n\nlet userNameWithId: any = 'luixaviles 1';\n// Como obtener el userName?\nuserName = (\u003cstring\u003euserNameWithId).substring(0, 10);\nconsole.log('userName', userName);\n\n// Sintaxis \"as\"\nlet message = (userName as string).length \u003e 5 ? ` Welcome ${userName}`: 'Username is too short';\n\nlet helloUser: any;\nhelloUser = 'hello paparazzi';\nuserName = (helloUser as string).substring(6);\nconsole.log('userName', userName);\n```\n\n## Funciones en TypeScript\n\n- Los parámetros en las funciones son tipados.\n- Se pueden definir parámetros opcionales.\n- El tipo de retorno puede ser un tipo básico, enum, alias, tipo literal o una combinación de ellos.\n\n```typescript\n// Funciones\n// crear una fotografía\n// JS\nfunction cratePictureJS(title, date, size) {\n    // los parámetros son de tipo any\n}\n\ntype SquareSizes = '100x100' | '500x500' | '1000x1000';\n\n// TS\nfunction createPictureTS(title: string, date: string, size: SquareSizes) {\n    // Se crea una fotografía\n    console.log('create picture using', title, date, size);\n}\n\ncratePictureTS('My Birthday', '10/10/2016', '100x100');\n\n// Parámetros opcionales\nfunction createPictureTS(title?: string, date?: string, size?: SquareSizes) {\n    // Se crea una fotografía\n    console.log('create picture using', title, date, size);\n}\n\n// El símbolo ? es para indicar que el parámetro es opcional\ncreatePictureTS('My Birthday', '10/10/2016');\ncreatePictureTS('My Birthday');\ncreatePictureTS();\n// de esta forma se vuelve opcional pasar todos los parámetros\n\n// ES6, fat arrow function\nlet createPic = (title: string, date: string, size: SquareSizes): object =\u003e {\n    return { title, date, size };\n};\n\nconst picture = createPic('My Birthday', '10/10/2016', '100x100');\nconsole.log('picture', picture);\n```\n\nUn parámetro opcional siempre debe ir añ final en el caso de que existan otros parámetros obligatorios.\n\n```typescript\n// Tipo de retorno con Typescript.\n\nfunction handleError(code: number, message: string): never | string {\n    // procesamiento del código, mensaje\n    if(message === 'error') {\n        throw new Error(`${message}. Code error ${code}`);\n    } else {\n        return 'an error has ocurred';\n    }\n}\n\n\ntry {\n    let result = handleError(200, 'OK'); // string\n    console.log('result', result); // an error has occurred\n    result = handleError(404, 'error'); // never\n    console.log('result', result);\n} catch(error) {\n\n}\n```\n\n![resumen](https://static.platzi.com/media/user_upload/Screen%20Shot%202020-07-18%20at%2012.16.38-ea16d15f-18a3-4476-adc4-49d669c279d0.jpg)\n\n## Interfaces\n\nLas interfaces en Typescript constituyen una forma poderosa de definir \"contratos\" tanto para tu proyecto, como para el código externo del mismo.\n\n```typescript\n// Interfaces\n// Función para mostrar una fotografía\n\nenum PhotoOrientation {\n    Landscape,\n    Portrait,\n    Square,\n    Panorama\n}\n\ninterface Picture {\n    title: string;\n    date: string;\n    orientation: PhotoOrientation;\n}\n\nfunction showPicture(picture: Picture) {\n    console.log(`[title: ${picture.title},\n                    date: ${picture.date},\n                    orientation: ${picture.orientation}]`);\n}\n\nlet myPic = {\n    title: 'My Birthday',\n    date: '10/10/2016',\n    orientation: PhotoOrientation.Landscape\n};\n\nshowPicture(myPic);\nshowPicture({\n    title: 'Test title',\n    date: '10/10/2016',\n    orientation: PhotoOrientation.Portrait,\n    // extra: 'extra' // Error\n});\n```\n\nUna interfaz en Typescript es en cierto sentido como un tipo (como string, number, boolean, etc) mas \"complejo\", en el cual defines (como en enum un contrato) las propiedades y métodos que se deben cumplir en cualquier objeto que implemente dicha interfaz. La diferencia entre una interfaz y una clase es que en la interfaz solo hacemos mención de que esperamos de un objeto, en una clase mencionamos las propiedades (igual que en una interfaz) pero definimos los métodos (osea, especificamos que hará ese método, en la interfaz solo mencionamos el nombre de la función).\n\n### Interfaces Propiedades opcionales\n\nNo todas las propiedades de una interfaz podrían ser requeridas.\n\nEstablecemos una propiedad como opcional con el símbolo `?` después del nombre de la propiedad.\n\n```typescript\ninterface PictureConfig {\n    title?: string;\n    date?: string;\n    orientation?: PhotoOrientation;\n}\n\nfunction generatePicture(config: PictureConfig) {\n    const pic = {title: 'default', date: '10/10/2016'}\n    if(config.title) {\n        pic.title = config.title;\n    }\n    if(config.date) {\n        pic.date = config.date;\n    }\n\n    return pic;\n}\n\nlet picture = generatePicture({}); // {title: 'default', date: '10/10/2016'}\npicture = generatePicture({title: 'Travel pic'}); // {title: 'Travel pic', date: '10/10/2016'}\npicture = generatePicture({title: 'Travel pic' ,date: '17/17/2017'}); // {title: 'Travel pic', date: '17/17/2017'}\n```\n\n### Interfaces Propiedades de Solo Lectura\n\nAlgunas propiedades de una interfaz pueden ser de solo lectura. Esto significa que no se puede cambiar su valor, pero si se puede acceder a su valor. Esto es posible usando `readonly` antes del nombre de la propiedad.\n\n```typescript\n// Interfaz Usuario\ninterface User {\n    readonly id: number; // id es de solo lectura\n    userName: string;\n    isPro: boolean;\n}\n\nlet user: User;\nuser = {id: 1, userName: 'John', isPro: true};\nuser.id = 2; // Error readonly property\nuser.userName = 'Juan';\n```\n\nEsto es util ya que en ciertos casos no queremos que se modifiquen ciertos valores ya que estos pueden ser importantes, como en el caso de una id de usuario en el contexto de una base de datos.\n\n### Extendiendo Interfaces\n\nLas interfaces pueden extenderse unas de otras. Esto permite copiar los miembros ya definidos en una interfaz a otra, ganando flexibilidad y reusabilidad de componentes.\n\n```Typescript\nexport {};\n\nenum PhotoOrientation {\n    Landscape,\n    Portrait,\n    Square,\n    Panorama,\n}\n\ninterface Entity {\n    id: number;\n    title: string;\n}\n\ninterface Album extends Entity {\n    // copia de los atributos de Entity\n    description: string;\n}\n\ninterface Picture extends Entity {\n    // copia de los atributos de Entity\n    orientation: PhotoOrientation;\n}\n\nconst album: Album = {\n    id: 1,\n    title: 'Meetings',\n    description: 'Photos taken during meetings',\n};\n\nconst picture: Picture = {\n    id: 2,\n    title: 'Family',\n    orientation: PhotoOrientation.Landscape,\n};\n\nlet newPicture = {} as Picture;\nnewPicture.id = 3;\nnewPicture.title = 'Friends';\n\nconsole.log(album);\nconsole.log(picture);\nconsole.log(newPicture);\n```\n\n## Clases\n\nSe supone que estamos haciendo una aplicación para fotografias, en donde tenemos 4 entidades ``User``, ``Album``, ``Picture``, ``\u003c\u003cenum\u003e\u003e PhotoOrientation``. Gracias al uso de ``clases`` y la ``programación orientada a objetos`` podemos lograr que esta entidades se relaciones de cierta forma.\n\n![poo](./img/poo.png)\n\n### Definiendo Clases y Constructores\n\nA partir de ECMAScript 2015 es posible construir clases y hacer uso del paradigma de la Programación Orientada a Objetos en JavaScript.\n\nTypescript permite aplicar estas técnicas sin tener que esperar por otra versión.\n\n```typescript\nexport { }\n\nenum PhotoOrientation {\n    Landscape,\n    Portrait,\n    Square,\n    Panorama,\n}\n\nclass Picture {\n    // Propiedades\n    id: number;\n    title: string;\n    orientation: PhotoOrientation;\n\n    // Constructor\n    constructor(\n        id: number,\n        title: string,\n        orientation: PhotoOrientation\n    ) {\n        this.id = id;\n        this.title = title;\n        this.orientation = orientation;\n    }\n\n    // Métodos\n    toString() {\n        return `[id: ${this.id},\n             title: ${this.title}, \n             orientation: ${this.orientation}]`;\n    }\n}\n\nclass Album {\n    id: number;\n    title: string;\n    pictures: Picture[];\n\n    constructor(id: number, title: string) {\n        this.id = id;\n        this.title = title;\n        this.pictures = [];\n    }\n\n    addPicture(picture: Picture) {\n        this.pictures.push(picture);\n    }\n}\n\nconst album: Album = new Album(1, 'Personal Pictures');\nconst picture: Picture = new Picture(1, 'my photos', PhotoOrientation.Square);\nalbum.addPicture(picture);\n\nconsole.log('Album' ,album);\n```\n\n## Clases públicas y privadas\n\nTypescript define un modificador de acceso público por defecto para miembros de clase.\n\nTambién es posible marcar un miembro como público usando la palabra reservada ``public``.\n\n### Clases Miembros Privados\n\nTypescript define una **manera propia** de declarar o marcar un miembro como privado usando la palabra reservada ``private``.\n\n```typescript\nclass Person {\n    private id: number;\n    private name: string;\n\n    public constructor(id: number, name: string) {\n        this.id = id;\n        this.name = name;\n    }\n\n    public getName(): string {\n        return this.name;\n    }\n}\n```\n\n### Miembros Privados en ECMAScript\n\nTypescript también soporta (a partir de la version 3.8) la nueva sintaxis JavaScript para miembros privados: ``#atributo``\n\nEsta característica puede ofrecer mejores garantías de aislamiento en miembros privados.\n\n```typescript\nclass Person {\n    #id: number;\n    #name: string;\n\n    public constructor(id: number, name: string) {\n        this.#id = id;\n        this.#name = name;\n    }\n\n    public getName(): string {\n        return this.#name;\n    }\n}\n```\n\n## Clases Métodos Set y Get\n\nTypescript soporta los métodos de acceso ``set`` y ``get`` como una forma de interceptar los accesos a los miembros privados de un objeto.\n\n```typescript\nclass Picture {\n    // Propiedades\n    private _id: number;\n    private _title: string;\n    private _orientation: PhotoOrientation;\n\n    // Constructor\n    public constructor(\n        id: number,\n        title: string,\n        orientation: PhotoOrientation\n    ) {\n        this._id = id;\n        this._title = title;\n        this._orientation = orientation;\n    }\n\n    get id() {\n        return this._id;\n    }\n\n    set id(id: number) {\n        this._id = id;\n    }\n\n    get title() {\n        return this._title;\n    }\n\n    set title(title: string) {\n        this._title = title;\n    }\n\n    get orientation() {\n        return this._orientation;\n    }\n\n    set orientation(orientation: PhotoOrientation) {\n        this._orientation = orientation;\n    }\n}\n```\n\nAl hacer esto podemos acceder a los miembros privados de una manera más segura.\n\n```typescript\npicture.id = 100; // private, set id(100);\npicture.title = 'My picture'; // private, set title('My picture');\n```\n\nPareciera que estamos cambiando el valor de una propiedad privada, pero en realidad estamos llamando a un método de acceso internamente.\n\n## Herencia de clases y propiedades estáticas\n\nTypescript soporta este patrón común en el mundo de la POO. Implementa la habilidad de extender código de clases existentes a través de la palabra reservada ``extends``.\n\n```typescript\nexport { }\n\nenum PhotoOrientation {\n    Landscape,\n    Portrait,\n    Square,\n    Panorama,\n}\n\n// SuperClase\nclass Item {\n    protected _id: number;\n    protected _title: string;\n\n    constructor(id: number, title: string) {\n        this._id = id;\n        this._title = title;\n    }\n\n    get id() {\n        return this._id;\n    }\n\n    set id(id: number) {\n        this._id = id;\n    }\n\n    get title() {\n        return this._title;\n    }\n\n    set title(title: string) {\n        this._title = title;\n    }\n}\n\n// get y set\n\nclass Picture extends Item {\n    // Propiedades\n    private _orientation: PhotoOrientation;\n\n    // Constructor\n    public constructor(\n        id: number,\n        title: string,\n        orientation: PhotoOrientation\n    ) {\n        super(id, title);\n        this._orientation = orientation;\n    }\n\n    get orientation() {\n        return this._orientation;\n    }\n\n    set orientation(orientation: PhotoOrientation) {\n        this._orientation = orientation;\n    }\n\n    // Métodos\n    public toString() {\n        return `[id: ${this.id},\n             title: ${this.title}, \n             orientation: ${this.orientation}]`;\n    }\n}\n\nclass Album extends Item {\n    private _pictures: Picture[];\n\n    public constructor(id: number, title: string) {\n        super(id, title);\n        this._pictures = [];\n    }\n\n    public addPicture(picture: Picture) {\n        this._pictures.push(picture);\n    }\n    \n}\n```\n\n## Clases Abstractas\n\nLas ``clases Abstractas`` son la base de donde otras clases podrían derivarse. A diferencia de una ``Interfaz``, una clase abstracta puede implementar funciones para sus instancias.\n\nLa palabra reservada ``abstract`` define una clase abstracta.\n\nLas clases abstractas no pueden ser instanciadas. Se usan para definir una clase base para otras clases derivadas, debido a esto no nos interesa instanciar una clase de este tipo, ya que no tiene mucho sentido.\n\n```typescript\nabstract class Item {\n    protected _id: number;\n    protected _title: string;\n}\n```\n\n## Propiedades Estáticas y propiedades de Solo Lectura\n\nLas clases por lo general definen atributos y métodos aplicables a las instancias de las mismas.\n\nA través de la palabra reservada ``static`` se pueden definir un miembro visible a nivel de clase.\n\nAl igual que las interfaces, podemos usar la palabra reservada ``readonly`` para marcar el miembro de una clase como solo lectura.\n\n```typescript\nexport { }\n\nenum PhotoOrientation {\n    Landscape,\n    Portrait,\n    Square,\n    Panorama,\n}\n\n// SuperClase\nabstract class Item {\n    protected readonly _id: number;\n    protected _title: string;\n\n    constructor(id: number, title: string) {\n        this._id = id;\n        this._title = title;\n    }\n\n    get id() {\n        return this._id;\n    }\n\n    get title() {\n        return this._title;\n    }\n\n    set title(title: string) {\n        this._title = title;\n    }\n}\n\n// get y set\n\nclass Picture extends Item {\n    public static photoOrientation = PhotoOrientation;\n    // Propiedades\n    private _orientation: PhotoOrientation;\n\n    // Constructor\n    public constructor(\n        id: number,\n        title: string,\n        orientation: PhotoOrientation\n    ) {\n        super(id, title);\n        this._orientation = orientation;\n    }\n\n    get orientation() {\n        return this._orientation;\n    }\n\n    set orientation(orientation: PhotoOrientation) {\n        this._orientation = orientation;\n    }\n\n    // Métodos\n    public toString() {\n        return `[id: ${this.id},\n             title: ${this.title}, \n             orientation: ${this.orientation}]`;\n    }\n}\n\nclass Album extends Item {\n    private _pictures: Picture[];\n\n    public constructor(id: number, title: string) {\n        super(id, title);\n        this._pictures = [];\n    }\n\n    public addPicture(picture: Picture) {\n        this._pictures.push(picture);\n    }\n    \n}\n\nconst album: Album = new Album(1, 'Personal Pictures');\nconst picture: Picture = new Picture(1, 'my photos', PhotoOrientation.Square);\nalbum.addPicture(picture);\n\nconsole.log('Album' ,album);\n\n// Accediendo a los miembros publicos\nconsole.log('picture.id', picture.id);\npicture.title = 'Nuevo titulo'; // private, set title('Nuevo titulo');\nalbum.title = 'Personal Activities'; // private, set title('Personal Activities');\nconsole.log('album', album);\n\n// Probar miembro estatico\nconsole.log('PhotoOrientation', Picture.photoOrientation.Landscape);\n```\n\n- ``abstract``: cuando requieres que una clase no sea instanciada, pero que pueda ser derivada.\n- ``protected``: atributo visible a nivel de clase y a nivel de quienes hereden de la clase con la palabra reservada ``extends``.\n- ``readonly``: atributo que solo puede ser leido, no puede ser modificado.\n- ``static``: para poder acceder a métodos/propiedades de una clase sin la necesidad de la instanciar.\n\n## Módulos en TypeScript\n\nLos módulos en Typescript proveen un mecanismo para una mejor organización del código y promueven su reutilización.\n\nA partir de ECMAScript 2015, los módulos son parte nativa del lenguaje JavaScript.\n\n### Importando y Exportando en Módulos\n\nGeneralmente se define un módulo con la idea de agrupar código relacionado.\n\nPodemos tomar criterios en torno a la funcionalidad, features, utilitarios, modelos, etc.\n\nLos miembros de módulos interactúan con el uso de las palabras reservadas ``import`` y ``export``.\n\n```typescript\n//photoApp.ts\nexport enum PhotoOrientation {\n    Landscape,\n    Portrait,\n    Square,\n    Panorama,\n}\n\nexport class User {\n    private album: Album[];\n\n    constructor(\n        private id: number,\n        private username: string,\n        private firstName: string,\n        private isPro: boolean,\n    ) {\n        this.album = [];\n    }\n\n    addAlbum(album: Album) {\n        this.album.push(album);\n    }\n}\n\nexport class Item {\n    constructor(public readonly id: number,\n        protected title: string) {\n    }\n}\n\nexport class Album extends Item {\n    picture: Picture[];\n\n    constructor(id: number, title: string) {\n        super(id, title);\n        this.picture = [];\n    }\n\n    addPicture(picture: Picture) {\n        this.picture.push(picture);\n    }\n}\n\nexport class Picture extends Item {\n    constructor(id: number,\n        title: string,\n        private _date: string,\n        private _orientation: PhotoOrientation) {\n        super(id, title);\n    }\n\n    toString(): string {\n        return `[id: ${this.id}, title: ${this.title}, orientation: ${this._orientation}]`;\n    }\n}\n```\n\n\n```typescript\n//main.ts\nimport { Album, PhotoOrientation, Picture, User } from \"./photoApp\";\n\nconst user = new User(1, 'pepe', 'Pedro', true);\nconst album = new Album(10, 'Fotos de familia');\nconst picture = new Picture(1, 'Fotos :)', '2021-02', PhotoOrientation.Landscape);\n\n// Creamos relaciones entre objetos\nuser.addAlbum(album);\nalbum.addPicture(picture);\n\nconsole.log('user', user);\n```\n\n## Principio de Responsabilidad Única\n\nIdealmente, un archivo debería tener un proposito o responsabilidad única: definir una clase, una interfaz, un enumerado, etc.\n\nEsto mejora la legibilidad del código, facilita su lectura, testing y favorece su mantenimiento.\n\n## Resolviendo Módulos\n\nTypescript resuelve la ubicación de módulos observando referencias relativas y no relativas.\n\nPosteriormente intenta localizar el módulo usando una **estrategia de resolución de módulos**.\n\n### Estrategia de resolución de módulos\n\nLa estrategia de resolución de módulos en typescript es completamente configurable.\n\nPodemos hacer uso del parámetro:\n\n```bash\ntsc --moduleResolution node\n```\n\nO\n\n```bash\ntsc --moduleResolution classic\n```\n\n![resolucion de modulos](./img/resolucion-de-modulos.png)\n\nEjemplo de como usar una clase:\n\n![ejemplo relativo](./img/ejemplo-relativo.png)\n\n![ejemplo no relativo](./img/ejemplo-no-relativo.png)\n\n![node import relativo](./img/node-import-relativo.png)\n\n![node import no relativo](./img/node-import-no-relativo.png)\n\nTambien existen los path alias para que no tengamos que lidiar con esa mano de puntos y slash en nuestros proyectos.\nEsta configuración la pueden poner en el tsconfig.json dentro de compilerOptions y así pueden acceder al shortcut @item para llegar a esa carpeta en específico que están buscando.\nPara el ejemplo yo tengo una carpeta item y dentro el archivo index.ts.\n\n```typescript\n\"paths\": {\n    \"@item\": [\"item/index.ts\"],\n}\n```\n\ny así se podría importar:\n\n```typescript\nimport { Item } from \"@item\";\n```\n\n## Webpack y agrupación de módulos\n\nWebpack es una herramienta bastante habitual para el desarrollo de aplicaciones web, podemos hace uso de dicha y herramienta y poder configurar junto con nuestro proyecto, para el procesamiento de cada una de nuestras clases o los archivos typescript.\n\nWebpack se considera un empaquetador de módulos o ``bundler``, y que ademas permite la integración con diferentes plugins o herramientas adicionales de configuración.\n\nPara usar Webpack en nuestro proyecto, debemos generar un archivo ``package.json``, que nos va a servir para definir un script de inicialización de webpack y ademas nos permite contener las diferentes dependencias en modo desarrollo.\n\n```bash\nnpm init -y\n```\n\nInstalacion de Typescript y Webpack:\n\n```bash\nnpm install typescript webpack webpack-cli --save-dev\n```\n\nPor defecto Webpack no reconocera nuestros archivos typescript, por lo que debemos configurarlo:\n\n```bash\nnpm install ts-loader --save-dev\n```","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdieg0code%2Ftsc_basics","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdieg0code%2Ftsc_basics","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdieg0code%2Ftsc_basics/lists"}