├── .eslintrc.json ├── .gitignore ├── LICENSE-APACHE-2.0 ├── LICENSE-MIT ├── README.md ├── app ├── grep │ ├── package.json │ └── tsconfig.json ├── submit-form │ ├── build-frontend.js │ ├── package.json │ ├── pnpm-lock.yaml │ ├── src │ │ ├── backend │ │ │ ├── .gitkeep │ │ │ └── templates │ │ │ │ ├── devserver.njk │ │ │ │ ├── header.njk │ │ │ │ ├── index.css │ │ │ │ ├── main.njk │ │ │ │ ├── server_message.njk │ │ │ │ ├── signin.njk │ │ │ │ ├── signup.njk │ │ │ │ └── welcome.njk │ │ └── frontend │ │ │ └── .gitkeep │ ├── tailwind.config.js │ └── tsconfig.json ├── todo │ ├── package.json │ └── tsconfig.json ├── weather-ui │ ├── assets │ │ └── static │ │ │ └── weather-icons │ │ │ └── reshot │ │ │ ├── LICENSE │ │ │ ├── clear.svg │ │ │ ├── cloudy.svg │ │ │ ├── drizzle.svg │ │ │ ├── fog.svg │ │ │ ├── info.svg │ │ │ ├── overcast.svg │ │ │ ├── rain.svg │ │ │ ├── snow.svg │ │ │ └── thunderstorm.svg │ ├── build-frontend.js │ ├── jest.config.js │ ├── package.json │ ├── pnpm-lock.yaml │ ├── src │ │ └── backend │ │ │ ├── location.test.ts │ │ │ ├── server.ts │ │ │ ├── templates │ │ │ ├── devserver.njk │ │ │ ├── get_started.njk │ │ │ ├── head.njk │ │ │ ├── index.css │ │ │ ├── main.njk │ │ │ └── weather.njk │ │ │ ├── weatherapi.test.ts │ │ │ └── weatherapi.ts │ ├── tailwind.config.js │ └── tsconfig.json └── weather │ ├── package.json │ ├── pnpm-lock.yaml │ ├── tsconfig.json │ ├── vite.config.js │ └── weatherapi.ts ├── check.js ├── demo ├── arithmetic │ ├── arithmetic.ts │ └── tsconfig.json ├── array-object │ ├── array-object.ts │ └── tsconfig.json ├── arrays │ ├── arrays.ts │ └── tsconfig.json ├── arrow-functions │ ├── arrow-functions.ts │ └── tsconfig.json ├── async-await │ ├── async-await.ts │ └── tsconfig.json ├── boolean-logic │ ├── boolean-logic.ts │ └── tsconfig.json ├── class-visibility │ ├── class-visibility.ts │ └── tsconfig.json ├── classes │ ├── classes.ts │ └── tsconfig.json ├── compound-bool │ ├── compound-bool.ts │ └── tsconfig.json ├── const-assert │ ├── const-assert.ts │ └── tsconfig.json ├── custom-iterator │ ├── custom-iterator.ts │ └── tsconfig.json ├── discriminated-unions │ ├── discriminated-unions.ts │ └── tsconfig.json ├── dmerge │ ├── dmerge.ts │ └── tsconfig.json ├── dts │ ├── dts.ts │ ├── mylib.js │ └── tsconfig.json ├── dts2 │ ├── dts2.ts │ ├── mylib.js │ └── tsconfig.json ├── exceptions │ ├── exceptions.ts │ └── tsconfig.json ├── functions │ ├── functions.ts │ └── tsconfig.json ├── generic-class │ ├── generic-class.ts │ └── tsconfig.json ├── generic-function │ ├── generic-function.ts │ └── tsconfig.json ├── gradual-typing │ ├── gradual-typing-1.ts │ ├── gradual-typing-2.ts │ └── tsconfig.json ├── if-else │ ├── if-else.ts │ └── tsconfig.json ├── increment │ ├── increment.ts │ └── tsconfig.json ├── interfaces │ ├── interfaces.ts │ └── tsconfig.json ├── iterators │ ├── iterators.ts │ └── tsconfig.json ├── maps │ ├── maps.ts │ └── tsconfig.json ├── modules │ ├── modules.ts │ ├── package.json │ └── tsconfig.json ├── objects │ ├── objects.ts │ └── tsconfig.json ├── optional-chaining │ ├── optional-chaining.ts │ └── tsconfig.json ├── optional-fields │ ├── optional-fields.ts │ └── tsconfig.json ├── repetition-for │ ├── repetition-for.ts │ └── tsconfig.json ├── repetition-while │ ├── repetition-while.ts │ └── tsconfig.json ├── switch │ ├── switch.ts │ └── tsconfig.json ├── tdoc │ ├── tdoc.ts │ └── tsconfig.json ├── template-strings │ ├── template-strings.ts │ └── tsconfig.json ├── ternary │ ├── ternary.ts │ └── tsconfig.json ├── testing │ ├── strings.ts │ └── tsconfig.json ├── tuples │ ├── tsconfig.json │ └── tuples.ts ├── type-alias │ ├── tsconfig.json │ └── type-alias.ts ├── type-annotations │ ├── tsconfig.json │ └── type-annotations.ts ├── type-assertions │ ├── tsconfig.json │ └── type-assertions.ts ├── type-predicates │ ├── tsconfig.json │ └── type-predicates.ts ├── unions │ ├── tsconfig.json │ └── unions.ts ├── variables │ ├── tsconfig.json │ └── variables.ts └── web │ ├── index.html │ ├── package.json │ ├── pnpm-lock.yaml │ ├── tsconfig.json │ └── vite.config.js ├── exercise ├── .gitkeep ├── array-object │ ├── 1.ts │ └── tsconfig.json ├── arrays │ ├── 1.ts │ ├── 2.ts │ └── tsconfig.json ├── arrow-functions │ ├── 1.ts │ ├── 2.ts │ ├── 3.ts │ └── tsconfig.json ├── async-await │ ├── 1.ts │ └── tsconfig.json ├── class-visibility │ ├── 1.ts │ └── tsconfig.json ├── classes │ ├── 1.ts │ ├── 2.ts │ └── tsconfig.json ├── compound-bool │ ├── 1.ts │ └── tsconfig.json ├── custom-iterator │ ├── 1.ts │ ├── 2.ts │ └── tsconfig.json ├── discriminated-unions │ ├── 1.ts │ ├── 2.ts │ └── tsconfig.json ├── dmerge │ ├── 1.ts │ ├── 2.ts │ └── tsconfig.json ├── exceptions │ ├── 1.ts │ ├── 2.ts │ └── tsconfig.json ├── functions │ ├── 1.ts │ ├── 2.ts │ ├── 3.ts │ ├── 4.ts │ └── tsconfig.json ├── generic-class │ ├── 1.ts │ ├── 2.ts │ └── tsconfig.json ├── generic-function │ ├── 1.ts │ ├── 2.ts │ └── tsconfig.json ├── gradual-typing │ ├── 1.ts │ ├── 2.ts │ ├── 3.ts │ └── tsconfig.json ├── if-else │ ├── 1.ts │ ├── 2.ts │ ├── 3.ts │ └── tsconfig.json ├── interfaces │ ├── 1.ts │ ├── 2.ts │ └── tsconfig.json ├── iterators │ ├── 1.ts │ ├── 2.ts │ ├── 3.ts │ └── tsconfig.json ├── maps │ ├── 1.ts │ ├── 2.ts │ ├── 3.ts │ └── tsconfig.json ├── optional-chaining │ ├── 1.ts │ ├── 2.ts │ ├── 3.ts │ └── tsconfig.json ├── repetition-for │ ├── 1.ts │ ├── 2.ts │ └── tsconfig.json ├── repetition-while │ ├── 1.ts │ └── tsconfig.json ├── switch │ ├── 1.ts │ ├── 2.ts │ └── tsconfig.json ├── ternary │ ├── 1.ts │ └── tsconfig.json ├── type-predicates │ └── 1.ts └── unions │ ├── 1.ts │ └── tsconfig.json ├── jest.config.js ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js ├── tailwind.config.js └── tsconfig.json /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "node": true 6 | }, 7 | "parser": "@typescript-eslint/parser", 8 | "extends": [ 9 | "standard-with-typescript", 10 | "plugin:@typescript-eslint/recommended", 11 | "plugin:@typescript-eslint/eslint-recommended", 12 | "plugin:@typescript-eslint/recommended-requiring-type-checking", 13 | "plugin:@typescript-eslint/strict", 14 | "plugin:import/recommended", 15 | "plugin:import/typescript", 16 | "prettier" 17 | ], 18 | "overrides": [], 19 | "parserOptions": { 20 | "ecmaVersion": "latest", 21 | "sourceType": "module", 22 | "project": [ 23 | "tsconfig.json" 24 | ] 25 | }, 26 | "ignorePatterns": [ 27 | "*.test.ts", 28 | "*.js" 29 | ], 30 | "rules": { 31 | "@typescript-eslint/method-signature-style": "off", 32 | "@typescript-eslint/no-explicit-any": "off", 33 | "@typescript-eslint/no-floating-promises": "off", 34 | "@typescript-eslint/no-non-null-assertion": "off", 35 | "@typescript-eslint/no-unsafe-call": "off", 36 | "@typescript-eslint/no-unsafe-member-access": "off", 37 | "@typescript-eslint/no-unsafe-assignment": "off", 38 | "@typescript-eslint/non-nullable-type-assertion-style": "off", 39 | "arrow-body-style": "error", 40 | "import/no-amd": "error", 41 | "import/no-commonjs": "error", 42 | "import/no-default-export": "error", 43 | "import/no-namespace": "warn", 44 | "import/no-webpack-loader-syntax": "error", 45 | "no-lone-blocks": "off", 46 | "@typescript-eslint/prefer-readonly": "off", 47 | "@typescript-eslint/restrict-template-expressions": "off", 48 | "@typescript-eslint/consistent-type-imports": [ 49 | "error", 50 | { 51 | "prefer": "type-imports" 52 | } 53 | ], 54 | "import/order": [ 55 | "error", 56 | { 57 | "groups": [ 58 | "builtin", 59 | "external", 60 | "parent", 61 | "sibling", 62 | "index", 63 | "object", 64 | "type" 65 | ], 66 | "pathGroups": [ 67 | { 68 | "pattern": "@/**/**", 69 | "group": "parent", 70 | "position": "before" 71 | } 72 | ], 73 | "alphabetize": { 74 | "order": "asc" 75 | } 76 | } 77 | ] 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | exercise/**/*.js 2 | demo/**/docs/ 3 | app/**/docs/ 4 | exercise/**/docs/ 5 | **/*.sqlite 6 | 7 | 8 | # https://github.com/github/gitignore/blob/main/Node.gitignore 9 | 10 | # Logs 11 | logs 12 | *.log 13 | npm-debug.log* 14 | yarn-debug.log* 15 | yarn-error.log* 16 | lerna-debug.log* 17 | .pnpm-debug.log* 18 | 19 | # Diagnostic reports (https://nodejs.org/api/report.html) 20 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 21 | 22 | # Runtime data 23 | pids 24 | *.pid 25 | *.seed 26 | *.pid.lock 27 | 28 | # Directory for instrumented libs generated by jscoverage/JSCover 29 | lib-cov 30 | 31 | # Coverage directory used by tools like istanbul 32 | coverage 33 | *.lcov 34 | 35 | # nyc test coverage 36 | .nyc_output 37 | 38 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 39 | .grunt 40 | 41 | # Bower dependency directory (https://bower.io/) 42 | bower_components 43 | 44 | # node-waf configuration 45 | .lock-wscript 46 | 47 | # Compiled binary addons (https://nodejs.org/api/addons.html) 48 | build/Release 49 | 50 | # Dependency directories 51 | node_modules/ 52 | jspm_packages/ 53 | 54 | # Snowpack dependency directory (https://snowpack.dev/) 55 | web_modules/ 56 | 57 | # TypeScript cache 58 | *.tsbuildinfo 59 | 60 | # Optional npm cache directory 61 | .npm 62 | 63 | # Optional eslint cache 64 | .eslintcache 65 | 66 | # Optional stylelint cache 67 | .stylelintcache 68 | 69 | # Microbundle cache 70 | .rpt2_cache/ 71 | .rts2_cache_cjs/ 72 | .rts2_cache_es/ 73 | .rts2_cache_umd/ 74 | 75 | # Optional REPL history 76 | .node_repl_history 77 | 78 | # Output of 'npm pack' 79 | *.tgz 80 | 81 | # Yarn Integrity file 82 | .yarn-integrity 83 | 84 | # dotenv environment variable files 85 | .env 86 | .env.development.local 87 | .env.test.local 88 | .env.production.local 89 | .env.local 90 | 91 | # parcel-bundler cache (https://parceljs.org/) 92 | .cache 93 | .parcel-cache 94 | 95 | # Next.js build output 96 | .next 97 | out 98 | 99 | # Nuxt.js build / generate output 100 | .nuxt 101 | dist 102 | 103 | # Gatsby files 104 | .cache/ 105 | # Comment in the public line in if your project uses Gatsby and not Next.js 106 | # https://nextjs.org/blog/next-9-1#public-directory-support 107 | # public 108 | 109 | # vuepress build output 110 | .vuepress/dist 111 | 112 | # vuepress v2.x temp and cache directory 113 | .temp 114 | .cache 115 | 116 | # Docusaurus cache and generated files 117 | .docusaurus 118 | 119 | # Serverless directories 120 | .serverless/ 121 | 122 | # FuseBox cache 123 | .fusebox/ 124 | 125 | # DynamoDB Local files 126 | .dynamodb/ 127 | 128 | # TernJS port file 129 | .tern-port 130 | 131 | # Stores VSCode versions used for testing VSCode extensions 132 | .vscode-test 133 | 134 | # yarn v2 135 | .yarn/cache 136 | .yarn/unplugged 137 | .yarn/build-state.yml 138 | .yarn/install-state.gz 139 | .pnp.* 140 | 141 | -------------------------------------------------------------------------------- /LICENSE-APACHE-2.0: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, and 10 | distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by the 13 | copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all other 16 | entities that control, are controlled by, or are under common control with 17 | that entity. For the purposes of this definition, "control" means (i) the 18 | power, direct or indirect, to cause the direction or management of such 19 | entity, whether by contract or otherwise, or (ii) ownership of 20 | fifty percent (50%) or more of the outstanding shares, or (iii) beneficial 21 | ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity exercising 24 | permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation source, 28 | and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical transformation 31 | or translation of a Source form, including but not limited to compiled 32 | object code, generated documentation, and conversions to 33 | other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or Object 36 | form, made available under the License, as indicated by a copyright notice 37 | that is included in or attached to the work (an example is provided in the 38 | Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object form, 41 | that is based on (or derived from) the Work and for which the editorial 42 | revisions, annotations, elaborations, or other modifications represent, 43 | as a whole, an original work of authorship. For the purposes of this 44 | License, Derivative Works shall not include works that remain separable 45 | from, or merely link (or bind by name) to the interfaces of, the Work and 46 | Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including the original 49 | version of the Work and any modifications or additions to that Work or 50 | Derivative Works thereof, that is intentionally submitted to Licensor for 51 | inclusion in the Work by the copyright owner or by an individual or 52 | Legal Entity authorized to submit on behalf of the copyright owner. 53 | For the purposes of this definition, "submitted" means any form of 54 | electronic, verbal, or written communication sent to the Licensor or its 55 | representatives, including but not limited to communication on electronic 56 | mailing lists, source code control systems, and issue tracking systems 57 | that are managed by, or on behalf of, the Licensor for the purpose of 58 | discussing and improving the Work, but excluding communication that is 59 | conspicuously marked or otherwise designated in writing by the copyright 60 | owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity on 63 | behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. 67 | 68 | Subject to the terms and conditions of this License, each Contributor 69 | hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, 70 | royalty-free, irrevocable copyright license to reproduce, prepare 71 | Derivative Works of, publicly display, publicly perform, sublicense, 72 | and distribute the Work and such Derivative Works in 73 | Source or Object form. 74 | 75 | 3. Grant of Patent License. 76 | 77 | Subject to the terms and conditions of this License, each Contributor 78 | hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, 79 | royalty-free, irrevocable (except as stated in this section) patent 80 | license to make, have made, use, offer to sell, sell, import, and 81 | otherwise transfer the Work, where such license applies only to those 82 | patent claims licensable by such Contributor that are necessarily 83 | infringed by their Contribution(s) alone or by combination of their 84 | Contribution(s) with the Work to which such Contribution(s) was submitted. 85 | If You institute patent litigation against any entity (including a 86 | cross-claim or counterclaim in a lawsuit) alleging that the Work or a 87 | Contribution incorporated within the Work constitutes direct or 88 | contributory patent infringement, then any patent licenses granted to 89 | You under this License for that Work shall terminate as of the date such 90 | litigation is filed. 91 | 92 | 4. Redistribution. 93 | 94 | You may reproduce and distribute copies of the Work or Derivative Works 95 | thereof in any medium, with or without modifications, and in Source or 96 | Object form, provided that You meet the following conditions: 97 | 98 | 1. You must give any other recipients of the Work or Derivative Works a 99 | copy of this License; and 100 | 101 | 2. You must cause any modified files to carry prominent notices stating 102 | that You changed the files; and 103 | 104 | 3. You must retain, in the Source form of any Derivative Works that You 105 | distribute, all copyright, patent, trademark, and attribution notices from 106 | the Source form of the Work, excluding those notices that do not pertain 107 | to any part of the Derivative Works; and 108 | 109 | 4. If the Work includes a "NOTICE" text file as part of its distribution, 110 | then any Derivative Works that You distribute must include a readable copy 111 | of the attribution notices contained within such NOTICE file, excluding 112 | those notices that do not pertain to any part of the Derivative Works, 113 | in at least one of the following places: within a NOTICE text file 114 | distributed as part of the Derivative Works; within the Source form or 115 | documentation, if provided along with the Derivative Works; or, within a 116 | display generated by the Derivative Works, if and wherever such 117 | third-party notices normally appear. The contents of the NOTICE file are 118 | for informational purposes only and do not modify the License. 119 | You may add Your own attribution notices within Derivative Works that You 120 | distribute, alongside or as an addendum to the NOTICE text from the Work, 121 | provided that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and may 125 | provide additional or different license terms and conditions for use, 126 | reproduction, or distribution of Your modifications, or for any such 127 | Derivative Works as a whole, provided Your use, reproduction, and 128 | distribution of the Work otherwise complies with the conditions 129 | stated in this License. 130 | 131 | 5. Submission of Contributions. 132 | 133 | Unless You explicitly state otherwise, any Contribution intentionally 134 | submitted for inclusion in the Work by You to the Licensor shall be under 135 | the terms and conditions of this License, without any additional 136 | terms or conditions. Notwithstanding the above, nothing herein shall 137 | supersede or modify the terms of any separate license agreement you may 138 | have executed with Licensor regarding such Contributions. 139 | 140 | 6. Trademarks. 141 | 142 | This License does not grant permission to use the trade names, trademarks, 143 | service marks, or product names of the Licensor, except as required for 144 | reasonable and customary use in describing the origin of the Work and 145 | reproducing the content of the NOTICE file. 146 | 147 | 7. Disclaimer of Warranty. 148 | 149 | Unless required by applicable law or agreed to in writing, Licensor 150 | provides the Work (and each Contributor provides its Contributions) 151 | on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 152 | either express or implied, including, without limitation, any warranties 153 | or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS 154 | FOR A PARTICULAR PURPOSE. You are solely responsible for determining the 155 | appropriateness of using or redistributing the Work and assume any risks 156 | associated with Your exercise of permissions under this License. 157 | 158 | 8. Limitation of Liability. 159 | 160 | In no event and under no legal theory, whether in tort 161 | (including negligence), contract, or otherwise, unless required by 162 | applicable law (such as deliberate and grossly negligent acts) or agreed 163 | to in writing, shall any Contributor be liable to You for damages, 164 | including any direct, indirect, special, incidental, or consequential 165 | damages of any character arising as a result of this License or out of 166 | the use or inability to use the Work (including but not limited to damages 167 | for loss of goodwill, work stoppage, computer failure or malfunction, 168 | or any and all other commercial damages or losses), even if such 169 | Contributor has been advised of the possibility of such damages. 170 | 171 | 9. Accepting Warranty or Additional Liability. 172 | 173 | While redistributing the Work or Derivative Works thereof, You may choose 174 | to offer, and charge a fee for, acceptance of support, warranty, 175 | indemnity, or other liability obligations and/or rights consistent with 176 | this License. However, in accepting such obligations, You may act only 177 | on Your own behalf and on Your sole responsibility, not on behalf of any 178 | other Contributor, and only if You agree to indemnify, defend, and hold 179 | each Contributor harmless for any liability incurred by, or claims 180 | asserted against, such Contributor by reason of your accepting any such 181 | warranty or additional liability. 182 | 183 | END OF TERMS AND CONDITIONS 184 | 185 | APPENDIX: How to apply the Apache License to your work 186 | 187 | To apply the Apache License to your work, attach the following boilerplate 188 | notice, with the fields enclosed by brackets "[]" replaced with your own 189 | identifying information. (Don't include the brackets!) The text should be 190 | enclosed in the appropriate comment syntax for the file format. We also 191 | recommend that a file or class name and description of purpose be included 192 | on the same "printed page" as the copyright notice for easier 193 | identification within third-party archives. 194 | 195 | Copyright 2024 Jayson Lennon 196 | 197 | Licensed under the Apache License, Version 2.0 (the "License"); 198 | you may not use this file except in compliance with the License. 199 | You may obtain a copy of the License at 200 | 201 | http://www.apache.org/licenses/LICENSE-2.0 202 | 203 | Unless required by applicable law or agreed to in writing, software 204 | distributed under the License is distributed on an "AS IS" BASIS, 205 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 206 | or implied. See the License for the specific language governing 207 | permissions and limitations under the License. 208 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 Jayson Lennon 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 16 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 18 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 19 | OR OTHER DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Running a Demo 2 | 3 | Using `ts-node`: 4 | 5 | `pnpm exec ts-node path/to/file.ts` 6 | 7 | Run a demo by invoking `tsc` and then `node`: 8 | 9 | `tsc -p path/to/directory && node path/to/file.js` 10 | 11 | Watch a specific demo directory and autobuild a JavaScript file when the TypeScript file changes: 12 | 13 | `tsc -w -p path/to/directory` 14 | 15 | and then run with 16 | 17 | `node path/to/file.js` 18 | 19 | ## Initial Setup 20 | 21 | `pnpm install` 22 | 23 | ## Running Tests 24 | 25 | `pnpm test exercise/FOLDER_NAME/*.test.ts` 26 | 27 | ## Type Checking 28 | 29 | `pnpm typecheck exercise/FOLDER_NAME` 30 | 31 | ## Linting 32 | 33 | `pnpm eslint exercise/FOLDER_NAME/FILE.ts` 34 | 35 | ## Build & Run Node 36 | 37 | `pnpm build exercise/FOLDER_NAME && node exercise/FOLDER_NAME/FILE_NAME.js` 38 | 39 | ## Generate docs 40 | 41 | cd demo/ANY_DIR && npx typedoc DEMO_FILE.ts 42 | 43 | -------------------------------------------------------------------------------- /app/grep/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ztm-typescript-grep", 3 | "version": "0.1.0", 4 | "license": "(MIT OR Apache-2.0)", 5 | "private": true, 6 | "author": "Jayson Lennon ", 7 | "homepage": "https://zerotomastery.io/courses/learn-typescript", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/jayson-lennon/ztm-typescript" 11 | }, 12 | "scripts": { 13 | "todo": "ts-node grep.ts" 14 | }, 15 | "devDependencies": { 16 | "@tsconfig/strictest": "^1.0.2", 17 | "@types/core-js": "^2.5.5", 18 | "@types/express": "^4.17.17", 19 | "@types/jest": "^29.5.1", 20 | "@types/node": "^18.16.3", 21 | "@typescript-eslint/eslint-plugin": "^5.59.2", 22 | "@typescript-eslint/parser": "^5.59.2", 23 | "eslint": "^8.39.0", 24 | "eslint-config-prettier": "^8.8.0", 25 | "eslint-config-standard-with-typescript": "^23.0.0", 26 | "eslint-plugin-import": "^2.27.5", 27 | "eslint-plugin-n": "^15.7.0", 28 | "eslint-plugin-promise": "^6.1.1", 29 | "jest": "^29.5.0", 30 | "ts-jest": "^29.1.0", 31 | "ts-node": "^10.9.1", 32 | "typescript": "^5.0.4", 33 | "vite": "^3.2.6", 34 | "vite-plugin-checker": "^0.5.6", 35 | "vite-plugin-eslint": "^1.8.1" 36 | }, 37 | "engines": { 38 | "node": ">=18.9.1" 39 | }, 40 | "dependencies": {} 41 | } 42 | -------------------------------------------------------------------------------- /app/grep/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /app/submit-form/build-frontend.js: -------------------------------------------------------------------------------- 1 | const browserify = require("browserify"); 2 | const tsify = require("tsify"); 3 | const fs = require("fs"); 4 | const { glob, globSync } = require('glob'); 5 | const path = require('path'); 6 | 7 | function copyFiles(pattern, destination) { 8 | const files = globSync(pattern); 9 | files.forEach((file) => { 10 | const fileName = path.basename(file); 11 | const destinationPath = path.join(destination, fileName); 12 | 13 | fs.copyFile(file, destinationPath, (err) => { 14 | if (err) { 15 | console.error(`Error copying file '${file}':`, err); 16 | return; 17 | } else { 18 | console.log(`copy '${file}' -> '${destinationPath}'`); 19 | } 20 | }); 21 | }); 22 | } 23 | 24 | const outputFile = fs.createWriteStream("./dist/sample.js"); 25 | 26 | fs.mkdirSync("./dist", { recursive: true }); 27 | 28 | browserify() 29 | .add("src/frontend/sample.ts") 30 | .plugin(tsify) 31 | .transform("babelify", { extensions: [".ts"] }) 32 | .transform("uglifyify", { global: true }) 33 | .bundle() 34 | .on("error", function(error) { console.error(error.toString()); }) 35 | .pipe(outputFile); 36 | 37 | copyFiles("assets/static/weather-icons/reshot/*.svg", "dist/static/img/"); 38 | -------------------------------------------------------------------------------- /app/submit-form/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ztm-typescript-submit-form", 3 | "version": "0.1.0", 4 | "license": "(MIT OR Apache-2.0)", 5 | "private": true, 6 | "author": "Jayson Lennon ", 7 | "homepage": "https://zerotomastery.io/courses/learn-typescript", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/jayson-lennon/ztm-typescript" 11 | }, 12 | "scripts": { 13 | "dev": "concurrently \"pnpm dev:tailwind\" \"pnpm dev:backend\" \"pnpm dev:frontend\" \"pnpm dev:reload\"", 14 | "dev:tailwind": "tailwindcss -w -i src/backend/templates/index.css -o dist/styles.css", 15 | "dev:backend": "nodemon -w ./src -e ts,njk,css --exec ts-node src/backend/server.ts", 16 | "dev:frontend": "nodemon -w ./src -e ts --exec parcel build src/frontend/**/*.ts", 17 | "dev:reload": "pnpm livereload -w 2000 -e html,css,njk,ts", 18 | "test": "jest", 19 | "lint": "eslint", 20 | "check": "node check.js" 21 | }, 22 | "devDependencies": { 23 | "@tailwindcss/typography": "^0.5.9", 24 | "@tsconfig/strictest": "^2.0.1", 25 | "@types/core-js": "^2.5.5", 26 | "@types/jest": "^29.5.1", 27 | "@types/node": "^20.1.0", 28 | "@typescript-eslint/eslint-plugin": "^5.59.2", 29 | "@typescript-eslint/parser": "^5.59.2", 30 | "concurrently": "^8.0.1", 31 | "eslint": "^8.40.0", 32 | "eslint-config-prettier": "^8.8.0", 33 | "eslint-config-standard-with-typescript": "^34.0.1", 34 | "eslint-plugin-import": "^2.27.5", 35 | "eslint-plugin-n": "^15.7.0", 36 | "eslint-plugin-promise": "^6.1.1", 37 | "jest": "^29.5.0", 38 | "livereload": "^0.9.3", 39 | "nodemon": "^2.0.22", 40 | "parcel": "^2.8.3", 41 | "postcss": "^8.4.23", 42 | "tailwindcss": "^3.3.2", 43 | "ts-jest": "^29.1.0", 44 | "ts-node": "^10.9.1", 45 | "typescript": "^5.0.4" 46 | }, 47 | "engines": { 48 | "node": ">=18.9.1" 49 | }, 50 | "dependencies": { 51 | "daisyui": "^2.51.6" 52 | } 53 | } 54 | 55 | -------------------------------------------------------------------------------- /app/submit-form/src/backend/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jayson-lennon/ztm-typescript/81b9e733ad6e891e1e4cafb0716f51d996b259dc/app/submit-form/src/backend/.gitkeep -------------------------------------------------------------------------------- /app/submit-form/src/backend/templates/devserver.njk: -------------------------------------------------------------------------------- 1 | {% if environment === 'dev' %} 2 | 10 | {% endif %} 11 | -------------------------------------------------------------------------------- /app/submit-form/src/backend/templates/header.njk: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/submit-form/src/backend/templates/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | -------------------------------------------------------------------------------- /app/submit-form/src/backend/templates/main.njk: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% include "header.njk" %} 6 | {% block header %}{% endblock %} 7 | 8 | {% block title %}Form Example{% endblock %} 9 | 10 | 11 | 12 | 13 | {% block content %}{% endblock %} 14 | 15 | {% include "devserver.njk" %} 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/submit-form/src/backend/templates/server_message.njk: -------------------------------------------------------------------------------- 1 | {% if server_msg %} 2 |

{{ server_msg }}

3 | {% endif %} 4 | -------------------------------------------------------------------------------- /app/submit-form/src/backend/templates/signin.njk: -------------------------------------------------------------------------------- 1 | {% extends "main.njk" %} 2 | 3 | {% block title %}Sign in{% endblock %} 4 | 5 | {% block content %} 6 |
7 |
8 |
9 |

Sign in

10 |

Sign in to the application

11 |
12 |
13 | {% include "server_message.njk" %} 14 |
15 |
16 | 19 | 21 | 23 |
24 |
25 | 29 | 31 | 33 |
34 |
35 |
36 | 37 |

New user? 38 | Create an account. 39 |

40 |
41 |
42 |
43 |
44 | 45 | {% endblock %} 46 | -------------------------------------------------------------------------------- /app/submit-form/src/backend/templates/signup.njk: -------------------------------------------------------------------------------- 1 | {% extends "main.njk" %} 2 | 3 | {% block title %}Sign up{% endblock %} 4 | 5 | {% block content %} 6 |
7 |
8 |
9 |

Sign up

10 |

Create an account

11 |
12 |
13 | {% include "server_message.njk" %} 14 |
15 |
16 | 19 | 21 | 23 |
24 |
25 | 29 | 31 | 33 |
34 |
35 | 41 |
42 |
43 |
44 | 45 |

Existing user? 46 | Sign in. 47 |

48 |
49 |
50 |
51 |
52 | 53 | {% endblock %} 54 | -------------------------------------------------------------------------------- /app/submit-form/src/backend/templates/welcome.njk: -------------------------------------------------------------------------------- 1 | {% extends "main.njk" %} 2 | 3 | {% block title %}Welcome!{% endblock %} 4 | 5 | {% block content %} 6 | Welcome to the site {{ email }}! 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /app/submit-form/src/frontend/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jayson-lennon/ztm-typescript/81b9e733ad6e891e1e4cafb0716f51d996b259dc/app/submit-form/src/frontend/.gitkeep -------------------------------------------------------------------------------- /app/submit-form/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | import typography from '@tailwindcss/typography'; 3 | import daisyui from 'daisyui'; 4 | 5 | export default { 6 | content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx,njk,html}"], 7 | theme: { 8 | extend: {}, 9 | }, 10 | plugins: [typography, daisyui], 11 | daisyui: { 12 | themes: [ 13 | { 14 | dark: { 15 | // ...require("daisyui/src/colors/themes")["[data-theme=dark]"], 16 | primary: "rgb(56, 189, 248)", 17 | }, 18 | }, 19 | ], 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /app/submit-form/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "ts-node": { 4 | "files": true 5 | }, 6 | "compilerOptions": { 7 | "module": "commonjs", 8 | "typeRoots": [ 9 | "./src/backend/types" 10 | ] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/todo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ztm-typescript-todo", 3 | "version": "0.1.0", 4 | "license": "(MIT OR Apache-2.0)", 5 | "private": true, 6 | "author": "Jayson Lennon ", 7 | "homepage": "https://zerotomastery.io/courses/learn-typescript", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/jayson-lennon/ztm-typescript" 11 | }, 12 | "scripts": { 13 | "todo": "ts-node todo.ts" 14 | }, 15 | "devDependencies": { 16 | "@tsconfig/strictest": "^1.0.2", 17 | "@types/core-js": "^2.5.5", 18 | "@types/express": "^4.17.17", 19 | "@types/jest": "^29.5.1", 20 | "@types/node": "^18.16.3", 21 | "@typescript-eslint/eslint-plugin": "^5.59.2", 22 | "@typescript-eslint/parser": "^5.59.2", 23 | "eslint": "^8.39.0", 24 | "eslint-config-prettier": "^8.8.0", 25 | "eslint-config-standard-with-typescript": "^23.0.0", 26 | "eslint-plugin-import": "^2.27.5", 27 | "eslint-plugin-n": "^15.7.0", 28 | "eslint-plugin-promise": "^6.1.1", 29 | "jest": "^29.5.0", 30 | "ts-jest": "^29.1.0", 31 | "ts-node": "^10.9.1", 32 | "typescript": "^5.0.4", 33 | "vite": "^3.2.6", 34 | "vite-plugin-checker": "^0.5.6", 35 | "vite-plugin-eslint": "^1.8.1" 36 | }, 37 | "engines": { 38 | "node": ">=18.9.1" 39 | }, 40 | "dependencies": {} 41 | } 42 | 43 | -------------------------------------------------------------------------------- /app/todo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /app/weather-ui/assets/static/weather-icons/reshot/LICENSE: -------------------------------------------------------------------------------- 1 | Reshot Free License 2 | 3 | Icons or Illustrations from Reshot can be used in: 4 | 5 | Social Media posts 6 | Online marketing ads 7 | Educational projects 8 | Commercial projects 9 | Editorial projects 10 | 11 | Items under the Reshot Free License can be used in your commercial and non-commercial projects, for free. 12 | 13 | You’re granted a copyright license to download, copy, modify, distribute, publicly perform and broadcast the Items. Your rights are non-exclusive, worldwide, sub-licensable and ongoing. Attribution is not required, however, we would appreciate it if you credit Reshot where reasonably possible. 14 | 15 | The Reshot Free License remains valid in perpetuity for downloaded photos used in your current projects. 16 | -------------------------------------------------------------------------------- /app/weather-ui/assets/static/weather-icons/reshot/clear.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/weather-ui/assets/static/weather-icons/reshot/cloudy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 13 | 14 | -------------------------------------------------------------------------------- /app/weather-ui/assets/static/weather-icons/reshot/drizzle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 10 | 14 | 18 | 19 | -------------------------------------------------------------------------------- /app/weather-ui/assets/static/weather-icons/reshot/fog.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 13 | 14 | -------------------------------------------------------------------------------- /app/weather-ui/assets/static/weather-icons/reshot/info.svg: -------------------------------------------------------------------------------- 1 | Info -------------------------------------------------------------------------------- /app/weather-ui/assets/static/weather-icons/reshot/overcast.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 18 | 19 | -------------------------------------------------------------------------------- /app/weather-ui/assets/static/weather-icons/reshot/rain.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 10 | 14 | 18 | 19 | -------------------------------------------------------------------------------- /app/weather-ui/assets/static/weather-icons/reshot/snow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 16 | 17 | -------------------------------------------------------------------------------- /app/weather-ui/assets/static/weather-icons/reshot/thunderstorm.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /app/weather-ui/build-frontend.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const { glob, globSync } = require('glob'); 3 | const path = require('path'); 4 | 5 | function copyFiles(pattern, destination) { 6 | const files = globSync(pattern); 7 | files.forEach((file) => { 8 | const fileName = path.basename(file); 9 | const destinationPath = path.join(destination, fileName); 10 | 11 | for (let i = 1; i < 3; i++) { 12 | try { 13 | fs.copyFileSync(file, destinationPath); 14 | console.log(`copy '${file}' -> '${destinationPath}'`); 15 | } catch (e) { 16 | if (e.code === "ENOENT") { 17 | const parent = path.dirname(destinationPath); 18 | fs.mkdirSync(parent, { recursive: true }); 19 | continue; 20 | } else { 21 | console.log(e); 22 | break; 23 | } 24 | } 25 | } 26 | }); 27 | } 28 | 29 | fs.mkdirSync("./dist", { recursive: true }); 30 | 31 | copyFiles("assets/static/weather-icons/reshot/*.svg", "dist/static/img/"); 32 | -------------------------------------------------------------------------------- /app/weather-ui/jest.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * For a detailed explanation regarding each configuration property and type check, visit: 3 | * https://jestjs.io/docs/configuration 4 | */ 5 | 6 | module.exports = { 7 | preset: 'ts-jest', 8 | testEnvironment: 'node', 9 | // All imported modules in your tests should be mocked automatically 10 | // automock: false, 11 | 12 | // Stop running tests after `n` failures 13 | // bail: 0, 14 | 15 | // The directory where Jest should store its cached dependency information 16 | // cacheDirectory: "/tmp/jest_rs", 17 | 18 | // Automatically clear mock calls, instances, contexts and results before every test 19 | clearMocks: true, 20 | 21 | // Indicates whether the coverage information should be collected while executing the test 22 | collectCoverage: true, 23 | 24 | // An array of glob patterns indicating a set of files for which coverage information should be collected 25 | // collectCoverageFrom: undefined, 26 | 27 | // The directory where Jest should output its coverage files 28 | coverageDirectory: "coverage", 29 | 30 | // An array of regexp pattern strings used to skip coverage collection 31 | coveragePathIgnorePatterns: [ 32 | "/node_modules/", 33 | ], 34 | 35 | // Indicates which provider should be used to instrument code for coverage 36 | coverageProvider: "v8", 37 | 38 | // A list of reporter names that Jest uses when writing coverage reports 39 | // coverageReporters: [ 40 | // "json", 41 | // "text", 42 | // "lcov", 43 | // "clover" 44 | // ], 45 | 46 | // An object that configures minimum threshold enforcement for coverage results 47 | // coverageThreshold: undefined, 48 | 49 | // A path to a custom dependency extractor 50 | // dependencyExtractor: undefined, 51 | 52 | // Make calling deprecated APIs throw helpful error messages 53 | // errorOnDeprecated: false, 54 | 55 | // The default configuration for fake timers 56 | // fakeTimers: { 57 | // "enableGlobally": false 58 | // }, 59 | 60 | // Force coverage collection from ignored files using an array of glob patterns 61 | // forceCoverageMatch: [], 62 | 63 | // A path to a module which exports an async function that is triggered once before all test suites 64 | // globalSetup: undefined, 65 | 66 | // A path to a module which exports an async function that is triggered once after all test suites 67 | // globalTeardown: undefined, 68 | 69 | // A set of global variables that need to be available in all test environments 70 | // globals: {}, 71 | 72 | // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. 73 | // maxWorkers: "50%", 74 | 75 | // An array of directory names to be searched recursively up from the requiring module's location 76 | // moduleDirectories: [ 77 | // "node_modules" 78 | // ], 79 | 80 | // An array of file extensions your modules use 81 | // moduleFileExtensions: [ 82 | // "js", 83 | // "mjs", 84 | // "cjs", 85 | // "jsx", 86 | // "ts", 87 | // "tsx", 88 | // "json", 89 | // "node" 90 | // ], 91 | 92 | // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module 93 | // moduleNameMapper: {}, 94 | 95 | // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader 96 | // modulePathIgnorePatterns: [], 97 | 98 | // Activates notifications for test results 99 | // notify: false, 100 | 101 | // An enum that specifies notification mode. Requires { notify: true } 102 | // notifyMode: "failure-change", 103 | 104 | // A preset that is used as a base for Jest's configuration 105 | // preset: undefined, 106 | 107 | // Run tests from one or more projects 108 | // projects: undefined, 109 | 110 | // Use this configuration option to add custom reporters to Jest 111 | // reporters: undefined, 112 | 113 | // Automatically reset mock state before every test 114 | // resetMocks: false, 115 | 116 | // Reset the module registry before running each individual test 117 | // resetModules: false, 118 | 119 | // A path to a custom resolver 120 | // resolver: undefined, 121 | 122 | // Automatically restore mock state and implementation before every test 123 | // restoreMocks: false, 124 | 125 | // The root directory that Jest should scan for tests and modules within 126 | // rootDir: undefined, 127 | 128 | // A list of paths to directories that Jest should use to search for files in 129 | // roots: [ 130 | // "" 131 | // ], 132 | 133 | // Allows you to use a custom runner instead of Jest's default test runner 134 | // runner: "jest-runner", 135 | 136 | // The paths to modules that run some code to configure or set up the testing environment before each test 137 | // setupFiles: [], 138 | 139 | // A list of paths to modules that run some code to configure or set up the testing framework before each test 140 | // setupFilesAfterEnv: [], 141 | 142 | // The number of seconds after which a test is considered as slow and reported as such in the results. 143 | // slowTestThreshold: 5, 144 | 145 | // A list of paths to snapshot serializer modules Jest should use for snapshot testing 146 | // snapshotSerializers: [], 147 | 148 | // The test environment that will be used for testing 149 | // testEnvironment: "jest-environment-node", 150 | 151 | // Options that will be passed to the testEnvironment 152 | // testEnvironmentOptions: {}, 153 | 154 | // Adds a location field to test results 155 | // testLocationInResults: false, 156 | 157 | // The glob patterns Jest uses to detect test files 158 | // testMatch: [ 159 | // "**/__tests__/**/*.[jt]s?(x)", 160 | // "**/?(*.)+(spec|test).[tj]s?(x)" 161 | // ], 162 | 163 | // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped 164 | // testPathIgnorePatterns: [ 165 | // "/node_modules/" 166 | // ], 167 | 168 | // The regexp pattern or array of patterns that Jest uses to detect test files 169 | // testRegex: [], 170 | 171 | // This option allows the use of a custom results processor 172 | // testResultsProcessor: undefined, 173 | 174 | // This option allows use of a custom test runner 175 | // testRunner: "jest-circus/runner", 176 | 177 | // A map from regular expressions to paths to transformers 178 | // transform: undefined, 179 | 180 | // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation 181 | // transformIgnorePatterns: [ 182 | // "/node_modules/", 183 | // "\\.pnp\\.[^\\/]+$" 184 | // ], 185 | 186 | // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them 187 | // unmockedModulePathPatterns: undefined, 188 | 189 | // Indicates whether each individual test should be reported during the run 190 | // verbose: undefined, 191 | 192 | // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode 193 | // watchPathIgnorePatterns: [], 194 | 195 | // Whether to use watchman for file crawling 196 | // watchman: true, 197 | }; 198 | -------------------------------------------------------------------------------- /app/weather-ui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ztm-typescript-submit-form", 3 | "version": "0.1.0", 4 | "license": "(MIT OR Apache-2.0)", 5 | "private": true, 6 | "author": "Jayson Lennon ", 7 | "homepage": "https://zerotomastery.io/courses/learn-typescript", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/jayson-lennon/ztm-typescript" 11 | }, 12 | "scripts": { 13 | "dev": "concurrently \"pnpm dev:tailwind\" \"pnpm dev:backend\" \"pnpm dev:frontend\" \"pnpm dev:reload\"", 14 | "dev:tailwind": "tailwindcss -w -i src/backend/templates/index.css -o dist/styles.css", 15 | "dev:backend": "nodemon -w ./src -e ts,njk,css --exec ts-node src/backend/server.ts", 16 | "dev:reload": "pnpm livereload -w 2500 -e html,css,njk,ts", 17 | "dev:frontend": "nodemon -w ./src -e ts --exec node build-frontend.js", 18 | "test": "jest", 19 | "lint": "eslint", 20 | "check": "node check.js" 21 | }, 22 | "devDependencies": { 23 | "@tailwindcss/typography": "^0.5.9", 24 | "@tsconfig/strictest": "^2.0.1", 25 | "@types/babelify": "^7.3.7", 26 | "@types/browserify": "^12.0.37", 27 | "@types/core-js": "^2.5.5", 28 | "@types/jest": "^29.5.1", 29 | "@types/node": "^20.1.0", 30 | "@types/nunjucks": "^3.2.2", 31 | "@typescript-eslint/eslint-plugin": "^5.59.2", 32 | "@typescript-eslint/parser": "^5.59.2", 33 | "axios-mock-adapter": "^1.21.4", 34 | "babelify": "^10.0.0", 35 | "browserify": "^17.0.0", 36 | "concurrently": "^8.0.1", 37 | "eslint": "^8.40.0", 38 | "eslint-config-prettier": "^8.8.0", 39 | "eslint-config-standard-with-typescript": "^34.0.1", 40 | "eslint-plugin-import": "^2.27.5", 41 | "eslint-plugin-n": "^15.7.0", 42 | "eslint-plugin-promise": "^6.1.1", 43 | "glob": "^10.2.3", 44 | "jest": "^29.5.0", 45 | "livereload": "^0.9.3", 46 | "nodemon": "^2.0.22", 47 | "path": "^0.12.7", 48 | "postcss": "^8.4.23", 49 | "tailwindcss": "^3.3.2", 50 | "ts-jest": "^29.1.0", 51 | "ts-node": "^10.9.1", 52 | "tsify": "^5.0.4", 53 | "typescript": "^5.0.4", 54 | "uglifyify": "^5.0.2" 55 | }, 56 | "engines": { 57 | "node": ">=18.9.1" 58 | }, 59 | "dependencies": { 60 | "@fastify/formbody": "^7.4.0", 61 | "@fastify/static": "^6.10.1", 62 | "axios": "^1.4.0", 63 | "dotenv": "^16.4.5", 64 | "fastify": "^4.17.0", 65 | "nunjucks": "^3.2.4", 66 | "zod": "^3.21.4" 67 | } 68 | } 69 | 70 | -------------------------------------------------------------------------------- /app/weather-ui/src/backend/location.test.ts: -------------------------------------------------------------------------------- 1 | const SAMPLE_API_RESPONSE = [ 2 | { 3 | place_id: 287781008, 4 | licence: 'Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright', 5 | powered_by: 'Map Maker: https://maps.co', 6 | osm_type: 'relation', 7 | osm_id: 207359, 8 | boundingbox: [Array], 9 | lat: '34.0536909', 10 | lon: '-118.242766', 11 | display_name: 'Los Angeles, Los Angeles County, California, United States', 12 | class: 'boundary', 13 | type: 'administrative', 14 | importance: 0.9738053728457621 15 | }, 16 | { 17 | place_id: 259239981, 18 | licence: 'Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright', 19 | powered_by: 'Map Maker: https://maps.co', 20 | osm_type: 'way', 21 | osm_id: 807458549, 22 | boundingbox: [Array], 23 | lat: '34.0708781', 24 | lon: '-118.44684973165106', 25 | display_name: 'University of California, Los Angeles, Bellagio Road, Bel Air, Bel-Air, Los Angeles, Los Angeles County, California, 90049, United States', 26 | class: 'amenity', 27 | type: 'university', 28 | importance: 0.8181396344174214 29 | }, 30 | ]; 31 | -------------------------------------------------------------------------------- /app/weather-ui/src/backend/server.ts: -------------------------------------------------------------------------------- 1 | const weatherCodeToImage = (code: number): string => { 2 | switch (code) { 3 | case 0: return "/static/img/clear.svg"; 4 | case 1: return "/static/img/clear.svg"; 5 | case 2: return "/static/img/cloudy.svg"; 6 | case 3: return "/static/img/overcast.svg"; 7 | case 45: return "/static/img/fog.svg"; 8 | case 48: return "/static/img/fog.svg"; 9 | case 51: return "/static/img/drizzle.svg"; 10 | case 53: return "/static/img/drizzle.svg"; 11 | case 55: return "/static/img/drizzle.svg"; 12 | case 56: return "/static/img/drizzle.svg"; 13 | case 57: return "/static/img/drizzle.svg"; 14 | case 61: return "/static/img/rain.svg"; 15 | case 63: return "/static/img/rain.svg"; 16 | case 65: return "/static/img/rain.svg"; 17 | case 66: return "/static/img/rain.svg"; 18 | case 67: return "/static/img/rain.svg"; 19 | case 71: return "/static/img/snow.svg"; 20 | case 73: return "/static/img/snow.svg"; 21 | case 75: return "/static/img/snow.svg"; 22 | case 77: return "/static/img/snow.svg"; 23 | case 80: return "/static/img/rain.svg"; 24 | case 81: return "/static/img/rain.svg"; 25 | case 82: return "/static/img/rain.svg"; 26 | case 85: return "/static/img/snow.svg"; 27 | case 86: return "/static/img/snow.svg"; 28 | case 95: return "/static/img/thunderstorm.svg"; 29 | case 96: return "/static/img/thunderstorm.svg"; 30 | case 99: return "/static/img/thunderstorm.svg"; 31 | default: return "/static/img/info.svg"; 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /app/weather-ui/src/backend/templates/devserver.njk: -------------------------------------------------------------------------------- 1 | {% if environment === 'dev' %} 2 | 10 | {% endif %} 11 | -------------------------------------------------------------------------------- /app/weather-ui/src/backend/templates/get_started.njk: -------------------------------------------------------------------------------- 1 | {% extends "main.njk" %} 2 | 3 | {% block title %}Weather{% endblock %} 4 | 5 | {% block content %} 6 |
7 |
9 | {% if serverMsg %} 10 |

{{ serverMsg }} 11 |

12 | {% endif %} 13 |
14 |

Enter a location to get started

15 |
16 |
17 |
18 | 22 |
23 | 26 |
27 |
28 |
29 | {% endblock %} 30 | -------------------------------------------------------------------------------- /app/weather-ui/src/backend/templates/head.njk: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/weather-ui/src/backend/templates/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | -------------------------------------------------------------------------------- /app/weather-ui/src/backend/templates/main.njk: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% include "head.njk" %} 6 | {% block head %}{% endblock %} 7 | 8 | {% block title %}Form Example{% endblock %} 9 | 10 | 11 | 12 | 13 | {% block content %}{% endblock %} 14 | 15 | {% include "devserver.njk" %} 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/weather-ui/src/backend/templates/weather.njk: -------------------------------------------------------------------------------- 1 | {% extends "main.njk" %} 2 | 3 | {% block title %}Weather{% endblock %} 4 | 5 | {% block content %} 6 |
7 |
9 | {% if serverMsg %} 10 |

{{ serverMsg }} 11 |

12 | {% endif %} 13 |
14 |

{{ location }}

15 |

{{ currentDate }}

16 |
17 |
18 | 19 |

{{ weather.condition }}

20 |
21 |
22 |
{{ weather.highTemp }}{{ weather.temperature.unit }}
23 |
/
24 |
{{ weather.lowTemp }}{{ weather.temperature.unit }}
25 |
26 |
27 |
28 | 32 |
33 | 36 |
37 |
38 |
39 | {% endblock %} 40 | -------------------------------------------------------------------------------- /app/weather-ui/src/backend/weatherapi.test.ts: -------------------------------------------------------------------------------- 1 | const SAMPLE_API_RESPONSE = { 2 | latitude: 36.16438, 3 | longitude: -115.143936, 4 | generationtime_ms: 0.23496150970458984, 5 | utc_offset_seconds: 0, 6 | timezone: 'GMT', 7 | timezone_abbreviation: 'GMT', 8 | elevation: 620, 9 | current_weather: { 10 | temperature: 30.7, 11 | windspeed: 15.3, 12 | winddirection: 27, 13 | weathercode: 0, 14 | is_day: 1, 15 | time: '2023-05-13T18:00' 16 | }, 17 | hourly_units: { time: 'iso8601', temperature_2m: '°C' }, 18 | hourly: { 19 | time: [ 20 | '2023-05-13T00:00', '2023-05-13T01:00', 21 | '2023-05-13T02:00', '2023-05-13T03:00', 22 | '2023-05-13T04:00', '2023-05-13T05:00', 23 | '2023-05-13T06:00', '2023-05-13T07:00', 24 | '2023-05-13T08:00', '2023-05-13T09:00', 25 | '2023-05-13T10:00', '2023-05-13T11:00', 26 | '2023-05-13T12:00', '2023-05-13T13:00', 27 | '2023-05-13T14:00', '2023-05-13T15:00', 28 | '2023-05-13T16:00', '2023-05-13T17:00', 29 | '2023-05-13T18:00', '2023-05-13T19:00', 30 | '2023-05-13T20:00', '2023-05-13T21:00', 31 | '2023-05-13T22:00', '2023-05-13T23:00' 32 | ], 33 | temperature_2m: [ 34 | 32.5, 32.1, 30.9, 28.7, 27.4, 35 | 26.4, 26, 26.1, 26, 24.7, 36 | 24.2, 23.8, 24, 23.3, 24.1, 37 | 25.7, 27.2, 28.6, 30.7, 31.6, 38 | 32.3, 33.4, 33.5, 33.5 39 | ] 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/weather-ui/src/backend/weatherapi.ts: -------------------------------------------------------------------------------- 1 | const weatherCodes: Record = { 2 | 0: "Clear sky", 3 | 1: "Mainly clear", 4 | 2: "Partly cloudy", 5 | 3: "Overcast", 6 | 45: "Fog", 7 | 48: "Depositing rime fog", 8 | 51: "Light drizzle", 9 | 53: "Moderate drizzle", 10 | 55: "Dense drizzle", 11 | 56: "Light freezing drizzle", 12 | 57: "Dense freezing drizzle", 13 | 61: "Slight rain", 14 | 63: "Moderate rain", 15 | 65: "Heavy rain", 16 | 66: "Light freezing rain", 17 | 67: "Heavy freezing rain", 18 | 71: "Slight snow fall", 19 | 73: "Moderate snow fall", 20 | 75: "Heavy snow fall", 21 | 77: "Snow grains", 22 | 80: "Slight rain showers", 23 | 81: "Moderate rain showers", 24 | 82: "Violent rain showers", 25 | 85: "Slight snow showers", 26 | 86: "Heavy snow showers", 27 | 95: "Moderate thunderstorm", 28 | 96: "Thunderstorm with slight hail", 29 | 99: "Thunderstorm with heavy hail", 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /app/weather-ui/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | import typography from '@tailwindcss/typography'; 3 | 4 | export default { 5 | content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx,njk,html}"], 6 | theme: { 7 | extend: {}, 8 | }, 9 | plugins: [typography], 10 | }; 11 | -------------------------------------------------------------------------------- /app/weather-ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "ts-node": { 4 | "files": true 5 | }, 6 | "exclude": [ 7 | "coverage" 8 | ], 9 | "compilerOptions": { 10 | "types": [ 11 | "@types/jest" 12 | ], 13 | "module": "commonjs", 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/weather/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ztm-typescript-weather", 3 | "version": "0.1.0", 4 | "license": "(MIT OR Apache-2.0)", 5 | "private": true, 6 | "author": "Jayson Lennon ", 7 | "homepage": "https://zerotomastery.io/courses/learn-typescript", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/jayson-lennon/ztm-typescript" 11 | }, 12 | "scripts": { 13 | "weather": "ts-node weather.ts" 14 | }, 15 | "devDependencies": { 16 | "@tsconfig/strictest": "^1.0.2", 17 | "@types/core-js": "^2.5.5", 18 | "@types/express": "^4.17.17", 19 | "@types/jest": "^29.5.1", 20 | "@types/node": "^18.16.3", 21 | "@typescript-eslint/eslint-plugin": "^5.59.2", 22 | "@typescript-eslint/parser": "^5.59.2", 23 | "eslint": "^8.39.0", 24 | "eslint-config-prettier": "^8.8.0", 25 | "eslint-config-standard-with-typescript": "^23.0.0", 26 | "eslint-plugin-import": "^2.27.5", 27 | "eslint-plugin-n": "^15.7.0", 28 | "eslint-plugin-promise": "^6.1.1", 29 | "jest": "^29.5.0", 30 | "ts-jest": "^29.1.0", 31 | "ts-node": "^10.9.1", 32 | "typescript": "^5.0.4", 33 | "vite": "^3.2.6", 34 | "vite-plugin-checker": "^0.5.6", 35 | "vite-plugin-eslint": "^1.8.1" 36 | }, 37 | "engines": { 38 | "node": ">=18.9.1" 39 | }, 40 | "dependencies": { 41 | "axios": "^1.4.0", 42 | "dotenv": "^16.4.5" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/weather/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /app/weather/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import eslint from "vite-plugin-eslint"; 3 | import checker from "vite-plugin-checker"; 4 | 5 | export default defineConfig({ 6 | plugins: [ 7 | eslint(), 8 | checker({ typescript: true }), 9 | ], 10 | }); 11 | -------------------------------------------------------------------------------- /app/weather/weatherapi.ts: -------------------------------------------------------------------------------- 1 | const weatherCodes: Record = { 2 | 0: "Clear sky", 3 | 1: "Mainly clear", 4 | 2: "Partly cloudy", 5 | 3: "Overcast", 6 | 45: "Fog", 7 | 48: "Depositing rime fog", 8 | 51: "Light drizzle", 9 | 53: "Moderate drizzle", 10 | 55: "Dense drizzle", 11 | 56: "Light freezing drizzle", 12 | 57: "Dense freezing drizzle", 13 | 61: "Slight rain", 14 | 63: "Moderate rain", 15 | 65: "Heavy rain", 16 | 66: "Light freezing rain", 17 | 67: "Heavy freezing rain", 18 | 71: "Slight snow fall", 19 | 73: "Moderate snow fall", 20 | 75: "Heavy snow fall", 21 | 77: "Snow grains", 22 | 80: "Slight rain showers", 23 | 81: "Moderate rain showers", 24 | 82: "Violent rain showers", 25 | 85: "Slight snow showers", 26 | 86: "Heavy snow showers", 27 | 95: "Moderate thunderstorm", 28 | 96: "Thunderstorm with slight hail", 29 | 99: "Thunderstorm with heavy hail", 30 | }; 31 | 32 | 33 | -------------------------------------------------------------------------------- /check.js: -------------------------------------------------------------------------------- 1 | const execSync = require('child_process').execSync; 2 | 3 | const path = process.argv[2]; 4 | 5 | try { 6 | execSync(`pnpm run typecheck ${path}`, { stdio: [0, 1, 2] }); 7 | execSync(`pnpm run lint ${path}`, { stdio: [0, 1, 2] }); 8 | } catch (_) { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /demo/arithmetic/arithmetic.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math 5 | // 6 | -------------------------------------------------------------------------------- /demo/arithmetic/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/array-object/array-object.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | -------------------------------------------------------------------------------- /demo/array-object/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/arrays/arrays.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Arrays offer a way to store and manipulate collections of values of the same 5 | // type. They are defined using square brackets and can be populated with 6 | // values at initialization, or later using various methods such as push(), 7 | // splice(), and concat(). Arrays can be of a fixed length or dynamically 8 | // resized as needed, and they can be used with various array methods to 9 | // perform common operations like sorting, filtering, and mapping. 10 | // 11 | // Useful links: 12 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array 13 | // 14 | -------------------------------------------------------------------------------- /demo/arrays/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/arrow-functions/arrow-functions.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // Arrow functions provide a concise syntax for defining functions. They are 4 | // defined using a fat arrow (=>) and can be used in place of traditional 5 | // function expressions. Arrow functions automatically bind the 'this' keyword 6 | // to the parent context, making them useful in event handlers and callback 7 | // functions. They also support implicit return statements for one-liner 8 | // functions, which makes the code more readable. 9 | // 10 | // Useful links: 11 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions 12 | // 13 | -------------------------------------------------------------------------------- /demo/arrow-functions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/async-await/async-await.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // `async/await` allows you to write asynchronous code in a synchronous way. 5 | // The `async` keyword used with a function or closure creates an asynchronous 6 | // context. The `await` keyword can be used inside an asynchronous context to 7 | // wait for a `Promise` to resolve before moving on to the next line of code. 8 | // While waiting, other code outside the function will execute. When the 9 | // promise resolves, the value is returned and assigned to the variable on the 10 | // left side of the `=` sign. This makes it easier to work with asynchronous 11 | // code as you can write code in a more sequential way. 12 | // 13 | // Useful links: 14 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function 15 | // https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Promises 16 | // 17 | -------------------------------------------------------------------------------- /demo/async-await/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/boolean-logic/boolean-logic.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Boolean logic is a fundamental concept that involves evaluating true/false 5 | // statements. It is a system of logical thought that uses true and false 6 | // values to make deductions or draw conclusions. Boolean logic is used to 7 | // express conditions and make decisions based on the truth or falsehood of 8 | // these conditions. 9 | // 10 | -------------------------------------------------------------------------------- /demo/boolean-logic/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/class-visibility/class-visibility.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Class visibility modifiers control the accessibility of class 5 | // members (properties and methods) from outside the class. 6 | // 7 | // The available visibility modifiers are 8 | // - `public`: accessible anywhere 9 | // - `protected`: accessible from the defining class and all subclasses 10 | // - `private`: accessible only within the defining class 11 | // 12 | // Using visibility modifiers helps to enforce encapsulation and prevent 13 | // unintended access to class members. 14 | // 15 | // Useful links: 16 | // https://www.typescriptlang.org/docs/handbook/2/classes.html#member-visibility 17 | // 18 | -------------------------------------------------------------------------------- /demo/class-visibility/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "noImplicitAny": false 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /demo/classes/classes.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Classes are a way to define blueprints for objects. They encapsulate data 5 | // and behavior and can be used to create instances of objects with predefined 6 | // properties and methods. Classes can be extended and inherited, allowing for 7 | // the creation of complex object hierarchies. 8 | // 9 | // Useful links: 10 | // https://www.typescriptlang.org/docs/handbook/2/classes.html 11 | // 12 | -------------------------------------------------------------------------------- /demo/classes/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/compound-bool/compound-bool.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | 5 | -------------------------------------------------------------------------------- /demo/compound-bool/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/const-assert/const-assert.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // `as const` allows you to create readonly values in your code. When you use 4 | // `as const` on an object, array or tuple, TypeScript infers that the values 5 | // are constant and cannot be modified later. This can help prevent unexpected 6 | // bugs in your code and make it easier to reason about. It's particularly 7 | // useful when working with APIs or configurations where values should not be 8 | // changed during runtime. 9 | // 10 | // Useful links: 11 | // https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions 12 | // 13 | -------------------------------------------------------------------------------- /demo/const-assert/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/custom-iterator/custom-iterator.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Useful links: 5 | // https://www.typescriptlang.org/docs/handbook/iterators-and-generators.html 6 | 7 | 8 | -------------------------------------------------------------------------------- /demo/custom-iterator/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/discriminated-unions/discriminated-unions.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // Discriminated unions are a way to declare a type that can have 4 | // different properties or behaviors based on a specific discriminator property. 5 | // Discriminated unions can be defined using the intersection of a set of types 6 | // with a common property, and the property value can be used to determine which 7 | // type to use. 8 | 9 | // We can also use entire objects. Using objects creates 10 | // a 'discriminated union'. Unions only allow the type to be one 11 | // option at a time. Combining this with objects allows multiple 12 | // pieces of data to be associated with each individual option. 13 | // 14 | -------------------------------------------------------------------------------- /demo/discriminated-unions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/dmerge/dmerge.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Declaration merging is a way to combine multiple declarations of 5 | // the same entity into a single definition. This allows you to extend existing 6 | // types and interfaces or merge them with new ones. Declaration merging is 7 | // particularly useful when working with third-party libraries or when you need 8 | // to add additional properties or methods to an existing type. 9 | // 10 | // Useful links: 11 | // https://www.typescriptlang.org/docs/handbook/declaration-merging.html 12 | // 13 | -------------------------------------------------------------------------------- /demo/dmerge/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/dts/dts.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Useful links: 5 | // https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-d-ts.html 6 | // 7 | -------------------------------------------------------------------------------- /demo/dts/mylib.js: -------------------------------------------------------------------------------- 1 | function add(a, b, ...args) { 2 | let total = a + b; 3 | for (let n of args) { 4 | total += n; 5 | } 6 | return total; 7 | } 8 | 9 | function max(arr) { 10 | if (arr.length === 0) { 11 | return null; 12 | } 13 | return arr.reduce((a, b) => Math.max(a, b)); 14 | } 15 | 16 | function setCase(message, kind) { 17 | if (kind === "uppercase") { 18 | return message.toUpperCase(); 19 | } else if (kind === "lowercase") { 20 | return message.toLowerCase(); 21 | } else { 22 | throw new Error("invalid kind: must be 'uppercase' or 'lowercase'"); 23 | } 24 | } 25 | 26 | function quote(message) { 27 | return () => { return `"${message}"` } 28 | } 29 | 30 | module.exports = { 31 | add, 32 | max, 33 | quote, 34 | setCase 35 | } 36 | 37 | -------------------------------------------------------------------------------- /demo/dts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/dts2/dts2.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Useful links: 5 | // https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-d-ts.html 6 | // 7 | -------------------------------------------------------------------------------- /demo/dts2/mylib.js: -------------------------------------------------------------------------------- 1 | function apiResponse() { 2 | return { 3 | "status": "success", 4 | "data": { 5 | "items": [ 6 | { 7 | "id": 1, 8 | "name": "Widget 1", 9 | "price": 10.99, 10 | "quantity": 50, 11 | "department": "Electronics" 12 | }, 13 | { 14 | "id": 2, 15 | "name": "Widget 2", 16 | "price": 19.99, 17 | "quantity": 25, 18 | "department": "Home & Kitchen" 19 | }, 20 | { 21 | "id": 3, 22 | "name": "Widget 3", 23 | "price": 5.99, 24 | "quantity": 100, 25 | "department": "Toys & Games" 26 | } 27 | ] 28 | } 29 | } 30 | } 31 | 32 | module.exports = { 33 | apiResponse 34 | } 35 | 36 | -------------------------------------------------------------------------------- /demo/dts2/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/exceptions/exceptions.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // Exceptions are a way to handle errors and unexpected behavior in your code. 4 | // When an exception occurs, it interrupts the normal flow of the program and 5 | // jumps to a predefined error-handling routine. Exceptions can be used to 6 | // catch and handle errors in a way that doesn't crash the program or cause 7 | // unexpected behavior. Exceptions are thrown using the `throw` keyword and 8 | // caught using the `try...catch` statement. 9 | // 10 | // Useful links: 11 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch 12 | // 13 | -------------------------------------------------------------------------------- /demo/exceptions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/functions/functions.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Functions are an essential component of programming that help organize code 5 | // and make it more modular. A function is a block of code that can be called 6 | // multiple times throughout a program with different inputs, allowing you to 7 | // reuse code and save time. Functions can perform specific tasks or return 8 | // values, and they can be used to break down complex problems into smaller, 9 | // more manageable pieces. By using functions, you can reduce redundancy, 10 | // improve code readability, and make it easier to maintain and update your 11 | // code. 12 | // 13 | // Useful links: 14 | // https://www.typescriptlang.org/docs/handbook/2/functions.html 15 | // 16 | -------------------------------------------------------------------------------- /demo/functions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "noImplicitAny": false 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /demo/generic-class/generic-class.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Generic classes offer the ability to define a class that can work with a 5 | // variety of different data types. By using generic type parameters, you can 6 | // create a single class that can be customized to work with any type of data 7 | // that you need. 8 | // 9 | // Similarly to generic functions, generic classes allow you to write more 10 | // flexible and reusable code, since you don't have to create a separate class 11 | // for every possible data type. 12 | // 13 | // Useful links: 14 | // https://www.typescriptlang.org/docs/handbook/2/generics.html#generic-classes 15 | // 16 | -------------------------------------------------------------------------------- /demo/generic-class/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "noImplicitAny": false 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /demo/generic-function/generic-function.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Generic functions are functions that are designed to work with different 5 | // types of data. They allow you to create a function that can be used with 6 | // various types of data without having to write a separate function for each 7 | // type. This makes your code more efficient, reusable, and easier to maintain. 8 | // Generic functions are especially useful when working with collections of 9 | // data, such as arrays, because they allow you to create a function that can 10 | // work with any type of data in the collection. 11 | // 12 | // Useful links: 13 | // https://www.typescriptlang.org/docs/handbook/2/generics.html#hello-world-of-generics 14 | // 15 | -------------------------------------------------------------------------------- /demo/generic-function/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "noImplicitAny": false 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /demo/gradual-typing/gradual-typing-1.ts: -------------------------------------------------------------------------------- 1 | // JavaScript 2 | 3 | function greetUsers(users): void { 4 | users.forEach(user => { 5 | console.log(`Hello, ${user.name}!`); 6 | }); 7 | } 8 | 9 | function getAverageAge(users): number { 10 | let totalAge = 0; 11 | users.forEach(user => { 12 | totalAge += user.age; 13 | }); 14 | return totalAge / users.length; 15 | } 16 | 17 | const users = [ 18 | { name: "Alice", age: 25 }, 19 | { name: "Bob", age: 30 }, 20 | { name: "Charlie", age: 35 } 21 | ]; 22 | 23 | greetUsers(users); 24 | console.log(`Average age: ${getAverageAge(users)}`); 25 | 26 | -------------------------------------------------------------------------------- /demo/gradual-typing/gradual-typing-2.ts: -------------------------------------------------------------------------------- 1 | // JavaScript 2 | 3 | function addItemToCart(cart, item, quantity) { 4 | if (!cart[item]) { 5 | cart[item] = 0; 6 | } 7 | cart[item] += quantity; 8 | } 9 | 10 | function calculateTotal(cart, prices) { 11 | let total = 0; 12 | for (const item in cart) { 13 | total += cart[item] * prices[item]; 14 | } 15 | return total; 16 | } 17 | 18 | function applyDiscount(total, discount) { 19 | return total * (1 - discount); 20 | } 21 | 22 | // Example usage 23 | const cart = {}; 24 | const prices = { 25 | apple: 1.0, 26 | banana: 0.5 27 | }; 28 | 29 | addItemToCart(cart, 'apple', 2); 30 | addItemToCart(cart, 'banana', 3); 31 | const total = calculateTotal(cart, prices); 32 | const discountedTotal = applyDiscount(total, 0.1); 33 | console.log(`Total after discount: $${discountedTotal}`); 34 | 35 | 36 | -------------------------------------------------------------------------------- /demo/gradual-typing/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "noImplicitAny": true 5 | } 6 | } -------------------------------------------------------------------------------- /demo/if-else/if-else.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Control flow is the order in which statements are executed in a program. It 5 | // allows programmers to control the flow of their code based on certain 6 | // conditions or events. Control flow structures include conditional 7 | // statements, loops, and function calls, which allow for branching and 8 | // repetition of code. 9 | // 10 | // Useful links: 11 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else 12 | // 13 | -------------------------------------------------------------------------------- /demo/if-else/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/increment/increment.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Incrementing numbers is a common task to perform when writing programs. So 5 | // common that there is an operator dedicated to just incrementing numbers. 6 | // However, it does come with a few caveats to be aware of. 7 | 8 | // Useful links: 9 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Increment 10 | // 11 | -------------------------------------------------------------------------------- /demo/increment/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/interfaces/interfaces.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Interfaces provide a way to define the shape of objects or classes. They 5 | // define the contracts that objects must follow, specifying the properties and 6 | // methods that an object must have. Interfaces make it easier to write 7 | // type-safe code by providing a way to ensure that objects are of the correct 8 | // shape before they are used in a program. They also allow for code to be more 9 | // modular and reusable, since objects can be easily swapped out as long as 10 | // they adhere to the interface's contract. 11 | // 12 | // Useful links: 13 | // https://www.typescriptlang.org/docs/handbook/2/objects.html 14 | // 15 | -------------------------------------------------------------------------------- /demo/interfaces/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/iterators/iterators.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // Iterators offer a way to traverse the elements of a collection one by one. 4 | // The purpose of iterators is to provide a standard way for accessing and 5 | // iterating over collections, such as arrays or maps, in a language-agnostic 6 | // way. Using iterators, you can iterate over collections in a loop without 7 | // having to worry about the underlying implementation of the collection. 8 | // 9 | // Useful links: 10 | // https://www.typescriptlang.org/docs/handbook/iterators-and-generators.html 11 | // 12 | -------------------------------------------------------------------------------- /demo/iterators/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/maps/maps.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // A `Map` is a data structure that allows you to store data in a key-value 5 | // pair format. Keys in a map must be unique, and each key can map to only one 6 | // value. You can use any type of value as the key, including objects and 7 | // functions. Maps are useful when you want to quickly access data and you are 8 | // able to maintain the key in memory. In situations where you have to search 9 | // (you don't have a key) for the data you need, a difference data structure 10 | // would be more appropriate. 11 | // 12 | // Useful links: 13 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map 14 | // 15 | -------------------------------------------------------------------------------- /demo/maps/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/modules/modules.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // ES modules provide a way to organize code into separate files that can be 5 | // imported and used in other files.To use an ES module, the the `import` 6 | // keyword is used. 7 | // 8 | // Useful links: 9 | // https://www.typescriptlang.org/docs/handbook/2/modules.html 10 | // 11 | -------------------------------------------------------------------------------- /demo/modules/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ztm-typescript-modules", 3 | "version": "0.1.0", 4 | "license": "(MIT OR Apache-2.0)", 5 | "private": true, 6 | "author": "Jayson Lennon ", 7 | "homepage": "https://zerotomastery.io/courses/learn-typescript", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/jayson-lennon/ztm-typescript" 11 | }, 12 | "scripts": { 13 | "devserver": "vite --clearScreen false --config vite.config.js", 14 | "test": "jest", 15 | "typecheck": "tsc --noEmit --strict -p", 16 | "lint": "eslint", 17 | "build": "tsc -p", 18 | "build-html": "vite build", 19 | "ts": "vite build", 20 | "check": "node check.js" 21 | }, 22 | "devDependencies": { 23 | "@tsconfig/strictest": "^1.0.2", 24 | "@types/core-js": "^2.5.5", 25 | "@types/express": "^4.17.17", 26 | "@types/jest": "^29.5.1", 27 | "@types/node": "^18.16.3", 28 | "@typescript-eslint/eslint-plugin": "^5.59.2", 29 | "@typescript-eslint/parser": "^5.59.2", 30 | "eslint": "^8.39.0", 31 | "eslint-config-prettier": "^8.8.0", 32 | "eslint-config-standard-with-typescript": "^23.0.0", 33 | "eslint-plugin-import": "^2.27.5", 34 | "eslint-plugin-n": "^15.7.0", 35 | "eslint-plugin-promise": "^6.1.1", 36 | "jest": "^29.5.0", 37 | "ts-jest": "^29.1.0", 38 | "ts-node": "^10.9.1", 39 | "typescript": "^5.0.4", 40 | "vite": "^3.2.6", 41 | "vite-plugin-checker": "^0.5.6", 42 | "vite-plugin-eslint": "^1.8.1" 43 | }, 44 | "engines": { 45 | "node": ">=18.9.1" 46 | }, 47 | "dependencies": {} 48 | } 49 | -------------------------------------------------------------------------------- /demo/modules/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": true, 5 | "allowImportingTsExtensions": true 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /demo/objects/objects.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Objects are a fundamental data type used to represent a collection of 5 | // properties with their respective values. They are defined using either an 6 | // object literal notation or a constructor notation. 7 | // 8 | // Useful links: 9 | // https://www.typescriptlang.org/docs/handbook/2/objects.html 10 | // 11 | -------------------------------------------------------------------------------- /demo/objects/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/optional-chaining/optional-chaining.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // Optional fields are convenient because they allow situations 4 | // where it may not be appropriate to have data present. However, 5 | // they make it cumbersome to access any additional data that is 6 | // behind the optional field. For example, trying to access multiple 7 | // optional objects one after the other requires multiple checks for 8 | // `undefined` and multiple `if` blocks. 9 | // 10 | // With 'Optional Chaining', it is possible to combine all of the `if` 11 | // blocks into a single line using the 'optional property access' operator. 12 | 13 | // The optional property access operator is a question mark (?) and allows 14 | // access to optional fields. It will continue to access optional fields 15 | // using the following behavior: 16 | // - Access fields until `undefined` is encountered, and then set the 17 | // expression to `undefined.` 18 | // - Access fields until the last field is accessed, and then set the 19 | // expression to the value of the last field. 20 | // 21 | // Useful links: 22 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining 23 | // 24 | -------------------------------------------------------------------------------- /demo/optional-chaining/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/optional-fields/optional-fields.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // You can define optional fields in your object types. Optional fields are 4 | // fields that may or may not be present in an object. You can make a field 5 | // optional by appending a question mark "?" to its name in the type 6 | // definition. This is useful when you have an object with some properties that 7 | // are not always required. 8 | // 9 | // Useful links: 10 | // https://www.typescriptlang.org/docs/handbook/2/objects.html#optional-properties 11 | 12 | 13 | -------------------------------------------------------------------------------- /demo/optional-fields/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/repetition-for/repetition-for.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // The `for` loop consists of three expressions separated by semicolons, 4 | // followed by curly braces where the loop body is placed. 5 | // 6 | // for (A;B;C) { } 7 | // 8 | // A: This is evaluated one time when the `for` loop is first encountered. 9 | // It is typically used to create a loop counter variable. 10 | // B: A boolean expression which is checked _before_ the loop executes 11 | // the next iteration. This is used to determine whether the loop 12 | // should continue. 13 | // C: An expression that is evaluated _after_ the loop body executes, on each 14 | // iteration. It is normally used to increment the loop counter created 15 | // in (A). 16 | // 17 | // Useful links: 18 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for 19 | // 20 | -------------------------------------------------------------------------------- /demo/repetition-for/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/repetition-while/repetition-while.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // A `while` loop executes the body while (as long as) some boolean expression 4 | // is `true`. It is your responsibility to manage when and how the loop exits. 5 | // 6 | // Useful links: 7 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/while 8 | // 9 | -------------------------------------------------------------------------------- /demo/repetition-while/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/switch/switch.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Useful links: 5 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch 6 | // 7 | -------------------------------------------------------------------------------- /demo/switch/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/tdoc/tdoc.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Useful links: 5 | // https://typedoc.org/ 6 | 7 | export function sqrt(x: number): number { 8 | return Math.sqrt(x); 9 | } 10 | 11 | export interface User { 12 | /** The unique identifier for the user. */ 13 | id: number; 14 | /** The user's full name. */ 15 | name: string; 16 | /** The user's email address. */ 17 | email: string; 18 | } 19 | 20 | export async function fetchUser(id: number): Promise { 21 | const response = await fetch(`/users/${id}`); 22 | if (!response.ok) { 23 | throw new Error(`Failed to fetch user: ${response.statusText}`); 24 | } 25 | return response.json() as Promise; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /demo/tdoc/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/template-strings/template-strings.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Template literals allow us to substitute variables into a string. 5 | // This makes it easy to display customized messages. 6 | // 7 | // Useful links: 8 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals 9 | // 10 | -------------------------------------------------------------------------------- /demo/template-strings/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "noImplicitAny": false 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /demo/ternary/ternary.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // 'ternary' is a condensed if..else statement that can fit on a 5 | // single line. 6 | // 7 | // Useful links: 8 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_operator 9 | // 10 | -------------------------------------------------------------------------------- /demo/ternary/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/testing/strings.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // Tests provide ways to confirm that your code works as intended. To create 4 | // tests you'll need to make a file having a filename of the file you want to 5 | // test, followed by `.test.ts`. For this demo, the test filename should be 6 | // `strings.test.ts`. 7 | // 8 | // Useful links: 9 | // https://jestjs.io/ 10 | 11 | // A basic function that concatenates two strings. 12 | export function concat(a: string, b: string): string { 13 | return `${a}${b}`; 14 | } 15 | 16 | export function div(lhs: number, rhs: number): number { 17 | if (rhs === 0) { 18 | throw new Error("Cannot divide by zero"); 19 | } else { 20 | return lhs / rhs; 21 | } 22 | } 23 | 24 | // An asynchronus function that resolves. 25 | export function slowString() { 26 | return new Promise((resolve, reject) => { 27 | setTimeout(() => { 28 | resolve("sample"); 29 | }, 200); 30 | }); 31 | } 32 | 33 | // An asynchronus function that fails. 34 | export function failedString() { 35 | return new Promise((resolve, reject) => { 36 | setTimeout(() => { 37 | reject("whoops"); 38 | }, 1); 39 | }); 40 | } 41 | 42 | -------------------------------------------------------------------------------- /demo/testing/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/tuples/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/tuples/tuples.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Tuples provide a way to express an array with a fixed number of elements of 5 | // different types, creating a data structure with multiple different types. 6 | // They can be especially handy when dealing with scenarios such as 7 | // representing coordinates, storing key-value pairs, or returning multiple 8 | // values from a function. Since they are type-checked, TypeScript can ensure 9 | // that the values in the tuple are correct at compile time. 10 | // 11 | // Useful links: 12 | // https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types 13 | // 14 | -------------------------------------------------------------------------------- /demo/type-alias/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/type-alias/type-alias.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Type aliases provide a way to give a name to a specific type or to create a 5 | // union of multiple types. They can be used to define object types, which can 6 | // then be used as types for variables, function parameters, and return types. 7 | // Type aliases offer a way to make your code more readable and maintainable by 8 | // providing descriptive names for complex types. 9 | // 10 | // Useful links: 11 | // https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-aliases 12 | // 13 | -------------------------------------------------------------------------------- /demo/type-annotations/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/type-annotations/type-annotations.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Type annotations are used to provide type information for variables, 5 | // functions, and other data structures in a program. By adding type 6 | // annotations, you can specify the expected types of data and prevent errors 7 | // that could occur from using the wrong type. This allows for better code 8 | // reliability, maintainability, and readability. 9 | // 10 | // Useful links: 11 | // https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-annotations-on-variables 12 | // 13 | -------------------------------------------------------------------------------- /demo/type-assertions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/type-assertions/type-assertions.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Type assertions allow you to tell the compiler that a value should be 5 | // considered a certain type, even if TypeScript cannot infer the type 6 | // automatically. You can use type assertions to help the compiler recognize 7 | // the types of variables, function return types, and more. When using type 8 | // assertions, be sure to only assert types that are actually correct, as 9 | // asserting an incorrect type can lead to runtime errors in your code. 10 | // 11 | // Useful links: 12 | // https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-assertions 13 | // 14 | -------------------------------------------------------------------------------- /demo/type-predicates/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/type-predicates/type-predicates.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { strict as assert } from "assert"; 3 | 4 | // Type predicates offer a way to determine the type of data based on a 5 | // condition. This is achieved by defining a function that takes a some data as 6 | // an argument, applies type guards, and returns a boolean indicating whether 7 | // the data is a specific type. The function is then used to narrow down the 8 | // type of the variable in subsequent code. Type predicates are useful when 9 | // dealing with union types or other situations where the type of a variable 10 | // may not be known at compile-time. Type predicates allow the type to be 11 | // determined correctly which avoids runtime errors. 12 | // 13 | // Useful links: 14 | // https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates 15 | // 16 | -------------------------------------------------------------------------------- /demo/unions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/unions/unions.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // Union types allows you to declare a variable or parameter that can hold 4 | // multiple types of value and are declared using the pipe symbol (|) between 5 | // the types. Union types can be useful when you want something to accept 6 | // multiple types of input. 7 | // 8 | // Useful links: 9 | // https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types 10 | // 11 | -------------------------------------------------------------------------------- /demo/variables/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/variables/variables.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // A variable is a named memory location that can hold a value. Variables can 4 | // be used to store a wide range of data types, such as numbers, strings, and 5 | // arrays. A variable is declared by specifying its name, data type, and 6 | // optionally an initial value. Once a variable is declared, it can be read 7 | // potentially updated in other parts of the program. 8 | // 9 | // Useful links: 10 | // https://www.typescriptlang.org/docs/handbook/variable-declarations.html#let-declarations 11 | // 12 | -------------------------------------------------------------------------------- /demo/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Web 8 | 9 | 10 | 11 |

12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /demo/web/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ztm-typescript-demo-web", 3 | "version": "0.1.0", 4 | "license": "(MIT OR Apache-2.0)", 5 | "private": true, 6 | "author": "Jayson Lennon ", 7 | "homepage": "https://zerotomastery.io/courses/learn-typescript", 8 | "type": "module", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/jayson-lennon/ztm-typescript" 12 | }, 13 | "scripts": { 14 | "devserver": "vite --clearScreen false --config vite.config.js" 15 | }, 16 | "devDependencies": { 17 | "@tsconfig/strictest": "^1.0.2", 18 | "@types/core-js": "^2.5.5", 19 | "@types/express": "^4.17.17", 20 | "@types/jest": "^29.5.1", 21 | "@types/node": "^18.16.3", 22 | "@typescript-eslint/eslint-plugin": "^5.59.2", 23 | "@typescript-eslint/parser": "^5.59.2", 24 | "eslint": "^8.39.0", 25 | "eslint-config-prettier": "^8.8.0", 26 | "eslint-config-standard-with-typescript": "^23.0.0", 27 | "eslint-plugin-import": "^2.27.5", 28 | "eslint-plugin-n": "^15.7.0", 29 | "eslint-plugin-promise": "^6.1.1", 30 | "jest": "^29.5.0", 31 | "ts-jest": "^29.1.0", 32 | "ts-node": "^10.9.1", 33 | "typescript": "^5.0.4", 34 | "vite": "^3.2.6", 35 | "vite-plugin-checker": "^0.5.6", 36 | "vite-plugin-eslint": "^1.8.1" 37 | }, 38 | "engines": { 39 | "node": ">=18.9.1" 40 | }, 41 | "dependencies": {} 42 | } 43 | 44 | -------------------------------------------------------------------------------- /demo/web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /demo/web/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import eslint from "vite-plugin-eslint"; 3 | import checker from "vite-plugin-checker"; 4 | 5 | export default defineConfig({ 6 | plugins: [ 7 | eslint(), 8 | checker({ typescript: true }), 9 | ], 10 | }); 11 | -------------------------------------------------------------------------------- /exercise/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jayson-lennon/ztm-typescript/81b9e733ad6e891e1e4cafb0716f51d996b259dc/exercise/.gitkeep -------------------------------------------------------------------------------- /exercise/array-object/1.ts: -------------------------------------------------------------------------------- 1 | // A student management system requires functionality to add and remove student 2 | // enrollments for various sections (classes). Each student has a list of 3 | // enrollments which may have sections added or removed at any time. 4 | // 5 | // The faculty also needs the ability to determine how many sections any given 6 | // student is enrolled in. 7 | // 8 | // Sections consist only of a section name, for example "Computer Science". 9 | // 10 | // Perform the following steps and add assertions to confirm that your program 11 | // behaves as expected: 12 | // 13 | // 1. Add a section titled "CompSci" for `alice` 14 | // 2. Add a section titled "Networking" for `alice` 15 | // 3. Remove a section titled "CompSci" from `alice` 16 | // 4. Assert that alice's enrollments consist of only "Networking" 17 | // 5. Add a section titled "Networking" for `bob` 18 | // 6. Assert that bob's enrollments consist of "Algorithms" and "Networking" 19 | // 7. Assert that bob's total enrollment count is equal to 2 20 | // 21 | // Tips: 22 | // 23 | // - Create an `addSection` function to add an enrollment for a student. 24 | // - Create a `removeSection` function to remove an enrollment from a student. 25 | // - Create a `totalEnrollments` function to calculate the number of 26 | // sections a student is enrolled in. 27 | 28 | import { strict as assert } from "assert"; 29 | 30 | const alice = { 31 | name: "Alice", 32 | enrollments: [], 33 | }; 34 | 35 | const bob = { 36 | name: "Bob", 37 | enrollments: ["Algorithms"], 38 | } 39 | 40 | 41 | -------------------------------------------------------------------------------- /exercise/array-object/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/arrays/1.ts: -------------------------------------------------------------------------------- 1 | // You received a small set of generated data from a client that looks like 2 | // it's out of order. The client noted that they have a bug report open to fix 3 | // the issue, but in the meantime you'll need to sort it out on your own. 4 | // 5 | // Since this data landed in your department and you love writing programs, you 6 | // decide to write one for this task instead of just swapping the values in 7 | // your text editor. 8 | // 9 | // The data set consists of two arrays where each element in one array is 10 | // associated with the element at the same index in the other array. For 11 | // example: 12 | // 13 | // [4, 2, 3] // ranks 14 | // ["brown", "gold", "purple"] // team colors 15 | // 16 | // Team "brown" ranked 8 while team "gold" ranked 2. 17 | // 18 | // Produce a program that can sort the two arrays in order from rank 1 to rank 19 | // 4. Using the example from above, the target arrays should look like this: 20 | // 21 | // [2, 3, 4] // ranks 22 | // ["gold", "purple", "brown"] // team colors 23 | // 24 | // In order to maximize billable hours, you opt to _not_ use the builtin 25 | // sorting functionality. 26 | // 27 | // Restrictions: 28 | // - Do not use the builtin sort method 29 | // - Do not use an indexing operations (no ranking[1] = ranking[2], for example) 30 | // - Only use array methods 31 | // 32 | // Notes: 33 | // - The solution does not need to work for any arbitrary data set. It only 34 | // needs to work for the given data set. 35 | // - You don't have to sort in-place (you can make a copy of the data). 36 | // 37 | // Perform the following steps and add assertions to confirm that your program 38 | // behaves as expected: 39 | // 40 | // 1. Sort the `ranking` and `teams` arrays given the above restrictions 41 | // 2. Assert that the `ranking` is [1, 2, 3, 4] and `teams` 42 | // is ["green", "yellow", "red", "blue"] 43 | // 3. Add team "pink" at rank 5 44 | // 4. Assert that the `ranking` is now [1, 2, 3, 4, 5] 45 | // and `teams` is ["green", "yellow", "red", "blue", "pink"] 46 | // 5. Sort the updated rankings in reverse order because the client called and 47 | // wants this done 48 | // 6. Assert that the `ranking` is now [5, 4, 3, 2, 1] 49 | // and `teams` is now ["pink", "blue", "red", "yellow", "green"] 50 | 51 | import { strict as assert } from "assert"; 52 | 53 | const ranking = [3, 4, 1, 2]; 54 | const teams = ["red", "blue", "green", "yellow"]; 55 | 56 | 57 | -------------------------------------------------------------------------------- /exercise/arrays/2.ts: -------------------------------------------------------------------------------- 1 | // An event organizer is hosting an event for IT vendors to showcase their 2 | // products. Each vendor gets a space of a specific size and has a short window 3 | // of time in which they can pitch their product. 4 | // 5 | // The organizers partitioned the area into "large" (over 10 units) and "small" 6 | // (10 units and under) spaces and want to figure out which vendors have small 7 | // spaces. They also want to be able to find which vendors have a specific 8 | // sized space based on the number of units. 9 | // 10 | // Finally, the organizers need to ability to adjust the total duration of each 11 | // presentation in case someone drops out. 12 | // 13 | // Perform the following: 14 | // 1. Create an array containing all vendors with a "small" sized space having 15 | // 10 or less units 16 | // 2. Determine if any vendors have a space of size 13 17 | // 3. Add 3 minutes to all presentation durations 18 | // 19 | // Run the program to test the existing assertions. 20 | 21 | import { strict as assert } from "assert"; 22 | 23 | const vendors = [ 24 | { size: 10, name: "Super Software", presentationDuration: 10 }, 25 | { size: 13, name: "Dyn-Data", presentationDuration: 8 }, 26 | { size: 7, name: "Engineering 2.0", presentationDuration: 12 } 27 | ]; 28 | 29 | 30 | // perform step 1 here 31 | const smallSpaces = []; // ... 32 | 33 | assert.deepStrictEqual(smallSpaces, (() => { 34 | const cloned = Array.from(vendors); 35 | cloned.splice(1, 1); 36 | return cloned; 37 | })()); 38 | 39 | // perform step 2 here 40 | const sizeExists = []; // ... 41 | 42 | assert.equal(sizeExists, true); 43 | 44 | // perform step 3 here 45 | const updatedDuration = []; // ... 46 | 47 | assert.deepStrictEqual(updatedDuration, 48 | [ 49 | { size: 10, name: "Super Software", presentationDuration: 13 }, 50 | { size: 13, name: "Dyn-Data", presentationDuration: 11 }, 51 | { size: 7, name: "Engineering 2.0", presentationDuration: 15 } 52 | ] 53 | ); 54 | 55 | -------------------------------------------------------------------------------- /exercise/arrays/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/arrow-functions/1.ts: -------------------------------------------------------------------------------- 1 | // You are tasked with creating a utility that processes an array of 2 | // numbers to find specific values. The array represents scores from a game, 3 | // and you need to manually iterate through the array to find the highest 4 | // score, the lowest score, and calculate the total sum of the scores. You'll 5 | // accomplish this using arrow functions. 6 | // 7 | // Requirements: 8 | // 9 | // - Use an arrow function to find the highest score 10 | // - Use an arrow function to find the lowest score 11 | // - Use an arrow function to calculate the sum of all scores 12 | // - Print out the highest score, lowest score, and the total sum. 13 | 14 | import { strict as assert } from "assert"; 15 | 16 | const scores: number[] = [15, 42, 23, 8, 37, 56, 14]; 17 | 18 | // Replace the 0 with a function call to your arrow functions. 19 | const maxScore = 0; 20 | const minScore = 0; 21 | const totalSum = 0; 22 | 23 | // Test cases. These will confirm if your answer is correct. 24 | assert.equal(maxScore, 56); 25 | assert.equal(minScore, 8); 26 | assert.equal(totalSum, 195); 27 | 28 | -------------------------------------------------------------------------------- /exercise/arrow-functions/2.ts: -------------------------------------------------------------------------------- 1 | // You are developing a small statistics module that needs to calculate the 2 | // average and median of an array of numbers. The array represents the scores 3 | // of students in an exam. You will use arrow functions to find the average and 4 | // median of these scores. 5 | // 6 | // Requirements: 7 | // - Use an arrow function to calculate the average of the numbers in the array. 8 | // - Use an arrow function to calculate the median of the numbers in the array. 9 | // - The array may have an even or odd number of elements, so handle both cases for the median. 10 | // - Print out the average and the median of the scores. 11 | 12 | import { strict as assert } from "assert"; 13 | 14 | const scores: number[] = [85, 92, 88, 74, 91, 77, 89, 95]; 15 | 16 | // Replace the 0 with a function call to your arrow functions. 17 | const average = 0; 18 | const median = 0; 19 | 20 | // Test cases. These will confirm if your answer is correct. 21 | assert.equal(average, 86.375); 22 | assert.equal(median, 88.5); 23 | 24 | 25 | -------------------------------------------------------------------------------- /exercise/arrow-functions/3.ts: -------------------------------------------------------------------------------- 1 | // You are building an event management system that filters and counts events 2 | // based on their type. You have an array of event objects, where each event 3 | // has a type and a name. You need to filter the events by a specific type and 4 | // count how many events match that type. You'll use arrow functions to 5 | // implement this functionality. 6 | // 7 | // Requirements: 8 | // - Use an arrow function to filter the events array array so it only has 9 | // "click" events. 10 | // - Use an arrow function to count the number of filtered "click" events. 11 | // - Print out the filtered events and the count of matching events. 12 | 13 | import { strict as assert } from "assert"; 14 | 15 | type Event = { 16 | type: string; 17 | name: string; 18 | } 19 | 20 | const events: Event[] = [ 21 | { type: "click", name: "Button Clicked" }, 22 | { type: "scroll", name: "Page Scrolled" }, 23 | { type: "click", name: "Link Clicked" }, 24 | { type: "hover", name: "Mouse Hovered" } 25 | ]; 26 | 27 | // Replace the `null` with a function call to your arrow functions. 28 | const clickEvents = null; 29 | const clickEventCount = null; 30 | 31 | // Test cases. These will confirm if your answer is correct. 32 | assert.deepStrictEqual(clickEvents, [ 33 | { type: "click", name: "Button Clicked" }, 34 | { type: "click", name: "Link Clicked" } 35 | ]); 36 | 37 | assert.equal(clickEventCount, 2); 38 | 39 | -------------------------------------------------------------------------------- /exercise/arrow-functions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/async-await/1.ts: -------------------------------------------------------------------------------- 1 | // Write an asynchronous function that calls the existing getUser function and 2 | // prints out the user's name. 3 | // 4 | // Note: The getUser function fails randomly. Make sure your function is able 5 | // to handle a failure scenario by printing out what went wrong. 6 | import { strict as assert } from "assert"; 7 | 8 | interface User { 9 | id: number; 10 | name: string; 11 | } 12 | 13 | async function getUser(): Promise { 14 | return await new Promise((resolve, reject) => { 15 | const [time1, time2] = [Math.floor(Math.random() * 200), Math.floor(Math.random() * 200)]; 16 | 17 | setTimeout(() => { 18 | resolve({ id: 1, name: "John" }); 19 | }, time1); 20 | setTimeout(() => { 21 | reject(new Error("failed to located user")); 22 | }, time2); 23 | }); 24 | } 25 | 26 | 27 | -------------------------------------------------------------------------------- /exercise/async-await/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/class-visibility/1.ts: -------------------------------------------------------------------------------- 1 | // You are enhancing a user management system where users have a name and a 2 | // role. Some details, such as the user's role, should be kept private and only 3 | // accessible through specific methods. You'll create a User class that 4 | // utilizes visibility modifiers to control access to its properties. 5 | // 6 | // Requirements: 7 | // - Create a `User` class with the following properties: 8 | // - `name`: A public string representing the user's name. 9 | // - `role`: A private string representing the user's role ("admin", 10 | // "guest"). 11 | // - Add a constructor to initialize both properties. 12 | // - Throw an exception if the role is not "admin" or "guest" 13 | // - Add a public method `getRole()` that returns the user's role. 14 | // - Add a public method `changeRole(newRole: string)` that updates the user's role. 15 | // - Throw an exception if the role is not "admin" or "guest" 16 | // - Perform the following actions: 17 | // 1. Create an instance of the `User` class 18 | // 2. Display the user's role using `getRole()` 19 | // 3. Change the role using `changeRole()` 20 | // 4. Attempt to directly access the private role property (which should 21 | // result in an error). 22 | 23 | import { strict as assert } from "assert"; 24 | 25 | // Create an instance of the User class. Replace `null` with your code. 26 | const user = null; 27 | 28 | // Display the user's role 29 | // 30 | // Put your code here 31 | // 32 | assert.equal(user.getRole(), "guest"); 33 | 34 | // Change the user's role 35 | // 36 | // Put your code here 37 | // 38 | assert.equal(user.getRole(), "admin"); 39 | 40 | // Attempt to access the private role property (this will cause a TypeScript 41 | // error if uncommented) 42 | // console.log(user.role); // Error: Property 'role' is private and only accessible within class 'User' 43 | 44 | // Attempt to set an invalid role (this will throw an error) 45 | try { 46 | // 47 | // Put your code here 48 | // 49 | } catch (e: any) { 50 | console.log(e.message); // Output: Invalid role 51 | } 52 | 53 | -------------------------------------------------------------------------------- /exercise/class-visibility/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/classes/1.ts: -------------------------------------------------------------------------------- 1 | // You are building a system to manage books in a library. Each book has a 2 | // title, an author, and a status indicating whether it is currently checked 3 | // out or available. You'll create a class to represent a book, with methods to 4 | // check the book out, return it, and display its information. 5 | // 6 | // Requirements: 7 | // - Create a `Book` class with the following properties: 8 | // - `title`: A string representing the title of the book. 9 | // - `author`: A string representing the author of the book. 10 | // - `isCheckedOut`: A boolean indicating whether the book is checked out 11 | // (initially false). 12 | // - Add a method `checkOut()` to the Book class that sets the `isCheckedOut` 13 | // property to true. 14 | // - Add a method `returnBook()` to the Book class that sets the `isCheckedOut` 15 | // property to false. 16 | // - Add a method displayInfo() to the Book class that prints out the `title`, 17 | // `author`, and `status` of the book. 18 | // - Create an instance of the `Book` class, check it out, display its 19 | // information, return it, and then display its information again. 20 | 21 | 22 | import { strict as assert } from "assert"; 23 | 24 | // Create an instance of the Book class. 25 | // 26 | // Replace `null` with your class instance. 27 | // 28 | const myBook = null; 29 | 30 | // Put your method calls to "check out" a book here. 31 | // 32 | assert.equal(myBook.isCheckedOut, true); 33 | 34 | // Put your method calls to "return" a book here. 35 | // 36 | assert.equal(myBook.isCheckedOut, false); 37 | 38 | -------------------------------------------------------------------------------- /exercise/classes/2.ts: -------------------------------------------------------------------------------- 1 | // You are tasked with creating some components for a video game. The first is 2 | // for managing the health of various game objects, and the second is for 3 | // managing a treasure chest. 4 | // 5 | // For managing health, create a class called "Health" that has this 6 | // functionality: 7 | // - Allows setting the initial amount of health 8 | // - Allows setting a maximum amount of health 9 | // - Has functionality to add health (increase current health) 10 | // - Has fucntionality to remove health (decrease current health) 11 | // 12 | // Additional notes: 13 | // - It should not be possible to go over the maximum amount of health 14 | // - Negative health is not allowed 15 | // 16 | // For managing treasure chests, create a class called "TreasureChest" that has 17 | // this functionality: 18 | // - Allows setting the content and the amount of the content. For example, a 19 | // treasure chest can contain an item called "Potion" and can hav a quantity 20 | // of 3. 21 | // - A method to open the treasure chest. When the treasure chest is opened, 22 | // the contents and quantity come out of the treasure chest which can then be 23 | // given to the player (player implementation not required. Just make sure 24 | // that the data is available so the player inventory can be updated later.) 25 | // 26 | // Additional notes: 27 | // - After opening a treasure chest and retrieving the contents, the player is 28 | // not allowed to get the items out again. Use any method you'd like to 29 | // implement this behavior. 30 | // 31 | // Perform the following steps to confirm that your Health class works 32 | // correctly: 33 | // - Make a new Health having the current health value set to 100 and the 34 | // maximum set to 200. 35 | // - Add 30 health 36 | // - Assert that the current health value is 130 37 | // - Add 500 health 38 | // - Assert that the current health value is 200 39 | // - Remove 500 health 40 | // - Assert that the current health value is 0 41 | // 42 | // Perform the following steps to confirm that your TreasureChest class works 43 | // correctly: 44 | // - Make a new TreasureChest having the contents of "gold" and a quantity of 45 | // 900 46 | // - Open the treasure chest and take out the contents and quantity 47 | // - Assert that the contents are "gold" and the quantity is 900 48 | // - Try to open the treasure chest again 49 | // - Assert that you _do not_ get "gold" and 900 again 50 | 51 | import { strict as assert } from "assert"; 52 | 53 | -------------------------------------------------------------------------------- /exercise/classes/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/compound-bool/1.ts: -------------------------------------------------------------------------------- 1 | // You are working on a simple access control system that determines whether a 2 | // user has the necessary permissions to access certain features of a website. 3 | // The system checks various conditions such as the user's role, whether they 4 | // are logged in, and whether they have accepted the terms and conditions. 5 | // You'll use Boolean logic to evaluate these conditions and make access 6 | // decisions. 7 | // 8 | // Requirements: 9 | // - For each scenario below, create a boolean expression that evaluates to 10 | // `true` whenever the user can access the feature, and `false` whenever the 11 | // user is denied access to the feature: 12 | // 1. When the user is logged in and has accepted the terms, then they can 13 | // access the feature. 14 | // 2. When the user is logged in but has _not_ accepted the terms, then they 15 | // _cannot_ access the feature. 16 | // 2. When the user is logged in and is an admin, they can access the feature 17 | 18 | /* eslint-disable */ 19 | 20 | import { strict as assert } from "assert"; 21 | 22 | // Scenario 1 23 | const isLoggedIn1 = true; 24 | const hasAcceptedTerms1 = true; 25 | const isAdmin1 = false; 26 | 27 | // Replace `null` with a boolean expression. 28 | const hasAccess1 = null; 29 | assert.equal(hasAccess1, true); // Should be true since the user is logged in and has accepted terms 30 | 31 | 32 | // Scenario 2 33 | const isLoggedIn2 = true; 34 | const hasAcceptedTerms2 = false; 35 | const isAdmin2 = false; 36 | 37 | // Replace `null` with a boolean expression. 38 | const hasAccess2 = null; 39 | assert.equal(hasAccess2, false); // Should be false since the user has not accepted terms and is not an admin 40 | 41 | 42 | // Scenario 3 43 | const isLoggedIn3 = false; 44 | const hasAcceptedTerms3 = false; 45 | const isAdmin3 = true; 46 | 47 | // Replace `null` with a boolean expression. 48 | const hasAccess3 = null; 49 | assert.equal(hasAccess3, true); // Should be true since the user is an admin 50 | 51 | 52 | -------------------------------------------------------------------------------- /exercise/compound-bool/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/custom-iterator/1.ts: -------------------------------------------------------------------------------- 1 | // You are working on a task that requires you to iterate over a sequence of 2 | // numbers. However, instead of creating the entire sequence upfront, you want 3 | // to generate the numbers one at a time as you iterate over them. You'll 4 | // create an iterator using a generator function that produces numbers in a 5 | // specified range. 6 | // 7 | // Requirements: 8 | // - Create a generator function named `range` that takes three parameters: 9 | // - `start`: A number indicating the starting value of the sequence. 10 | // - `end`: A number indicating the ending value of the sequence (inclusive). 11 | // - `step`: A number indicating the step between each value in the sequence. 12 | // - The generator should yield each number in the sequence from `start` to 13 | // `end` based on the `step` value. 14 | // - Use a `for...of` loop to iterate over the sequence generated by the range 15 | // function and print each number. 16 | // - Ensure that the range function works correctly when the step value is 17 | // positive, negative, or omitted (defaulting to 1). 18 | 19 | import { strict as assert } from "assert"; 20 | 21 | 22 | // Test cases 23 | const result1 = Array.from(range(1, 5, 1)); 24 | assert.deepEqual(result1, [1, 2, 3, 4, 5]); 25 | 26 | const result2 = Array.from(range(5, 1, -1)); 27 | assert.deepEqual(result2, [5, 4, 3, 2, 1]); 28 | 29 | const result3 = Array.from(range(1, 3)); 30 | assert.deepEqual(result3, [1, 2, 3]); 31 | 32 | -------------------------------------------------------------------------------- /exercise/custom-iterator/2.ts: -------------------------------------------------------------------------------- 1 | // You are building a utility that generates unique IDs for different elements 2 | // on a webpage. Each ID should be unique and sequential, following a specific 3 | // prefix. You'll use a generator function to create a sequence of these unique 4 | // IDs. 5 | // 6 | // Requirements: 7 | // - Create a generator function named `idGenerator` that takes a prefix string 8 | // as an argument. 9 | // - The generator should produce unique IDs by appending a sequential number 10 | // to the prefix. 11 | // - For example, if the prefix is "item-", then the final IDs should be 12 | // "item-1", "item-2", etc. 13 | // - Each time the generator is called using `next()`, it should return the 14 | // next ID in the sequence. 15 | // - Create an instance of the `idGenerator` function for generating IDs with 16 | // the prefix "item-". 17 | // - Generate three unique IDs using the `idGenerator` instance and print them 18 | // to the console. 19 | // - Test the generator by ensuring that the generated IDs are "item-1", 20 | // "item-2", and "item-3". 21 | 22 | import { strict as assert } from "assert"; 23 | 24 | // Create an instance of the idGenerator 25 | // 26 | // Replace `null` with a call to your `idGenerator` function. 27 | const itemIdGenerator = null; 28 | 29 | // Generate three unique IDs 30 | const id1 = itemIdGenerator.next().value; 31 | const id2 = itemIdGenerator.next().value; 32 | const id3 = itemIdGenerator.next().value; 33 | 34 | // Test cases 35 | assert.equal(id1, "item-1"); 36 | assert.equal(id2, "item-2"); 37 | assert.equal(id3, "item-3"); 38 | 39 | 40 | -------------------------------------------------------------------------------- /exercise/custom-iterator/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/discriminated-unions/1.ts: -------------------------------------------------------------------------------- 1 | // Write a program that calculates the total area of different shapes using 2 | // discriminated unions. Include support for at least squares, rectangles, and 3 | // circles. The functionality to calculate the area of each shape should exist 4 | // in a single function and the function should select the appropriate 5 | // calculation based on the disciminator. 6 | // 7 | // The area of a square: side^2 8 | // The area of a rectangle: width * height 9 | // The area of a circle: Math.PI * radius^2 10 | // 11 | // Make these assertions to check your code: 12 | // - Square with side length of 5 has an area of 25 13 | // - Rectangle with width of 4 and height of 6 has an area of 24 14 | // - Circle with radius of 3 has an area of Math.PI * 9 15 | 16 | import { strict as assert } from "assert"; 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /exercise/discriminated-unions/2.ts: -------------------------------------------------------------------------------- 1 | // You are developing a system to manage user notifications in a web 2 | // application. Notifications can be of different types, such as a message, an 3 | // error, or a success notification. Each notification type requires different 4 | // handling and contains different information. You'll use discriminated unions 5 | // to model the different notification types and handle them appropriately. 6 | // 7 | // Requirements: 8 | // - Define a discriminated union `Notification` that has three variants: 9 | // 1. `MessageNotification`: Represents a standard message notification with 10 | // the following properties: 11 | // - type: A string literal "message". 12 | // - text: A string containing the message content. 13 | // 2. `ErrorNotification`: Represents an error notification with the following 14 | // properties: 15 | // - type: A string literal "error". 16 | // - code: A number representing the error code. 17 | // - message: A string containing the error message. 18 | // 3. `SuccessNotification`: Represents a success notification with the 19 | // following properties: 20 | // - type: A string literal "success". 21 | // - text: A string containing the success message. 22 | // - Create a function `getNotification` that takes a `Notification` as a 23 | // parameter and returns a `string` with an appropriate message based on the 24 | // type of the notification. 25 | // - Format the message using the format provided for each test case. 26 | // - Use a `switch` statement to handle each variant of the `Notification` type 27 | // within the `getNotification` function. 28 | 29 | import { strict as assert } from "assert"; 30 | 31 | // Test cases 32 | // 33 | // Format: 34 | // "Message: " 35 | // 36 | // Example: 37 | // "Message: You have a new message 38 | const messageNotification: MessageNotification = { 39 | type: "message", 40 | text: "You have a new message." 41 | }; 42 | 43 | // Format: 44 | // "Error : " 45 | // 46 | // Example: 47 | // "Error 404: Page not found." 48 | const errorNotification: ErrorNotification = { 49 | type: "error", 50 | code: 404, 51 | message: "Page not found." 52 | }; 53 | 54 | // Format: 55 | // "Success: " 56 | // 57 | // Example: 58 | // "Success: Operation completed successfully." 59 | const successNotification: SuccessNotification = { 60 | type: "success", 61 | text: "Operation completed successfully." 62 | }; 63 | 64 | const case1 = getNotification(messageNotification); // Message: You have a new message. 65 | const case2 = getNotification(errorNotification); // Error 404: Page not found. 66 | const case3 = getNotification(successNotification); // Success: Operation completed successfully. 67 | 68 | assert.equal(case1, "Message: You have a new message."); 69 | assert.equal(case2, "Error 404: Page not found."); 70 | assert.equal(case3, "Success: Operation completed successfully."); 71 | 72 | -------------------------------------------------------------------------------- /exercise/discriminated-unions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/dmerge/1.ts: -------------------------------------------------------------------------------- 1 | // You are developing a library for handling geometric shapes. The library 2 | // provides basic shape types like Circle and Rectangle. You need to add 3 | // additional methods to these shape types to calculate their area and 4 | // perimeter using declaration merging. 5 | // 6 | // Requirements: 7 | // 8 | // - Define an initial interface Circle with the following property: 9 | // - radius: A number representing the radius of the circle. 10 | // - Define an initial interface Rectangle with the following properties: 11 | // - width: A number representing the width of the rectangle. 12 | // - height: A number representing the height of the rectangle. 13 | // - Use declaration merging to extend the Circle interface with methods: 14 | // - area(): A method that calculates and returns the area of the circle. 15 | // - perimeter(): A method that calculates and returns the perimeter of the 16 | // circle. 17 | // - Use declaration merging to extend the Rectangle interface with methods: 18 | // - area(): A method that calculates and returns the area of the rectangle. 19 | // - perimeter(): A method that calculates and returns the perimeter of the 20 | // rectangle. 21 | // - Create instances of Circle and Rectangle, calculate their area and 22 | // perimeter using the newly added methods, and print the results. 23 | 24 | import { strict as assert } from "assert"; 25 | 26 | // Replace `null` with an instance of `Circle`. 27 | const circle = null; 28 | 29 | // Replace `null` with an instance of `Rectangle`. 30 | const rectangle = null; 31 | 32 | // Test cases 33 | circle.radius = 5; 34 | assert.equal(circle.area(), Math.PI * 5 * 5); 35 | assert.equal(circle.perimeter(), 2 * Math.PI * 5); 36 | rectangle.width = 10; 37 | rectangle.height = 4; 38 | assert.equal(rectangle.area(), 10 * 4); 39 | assert.equal(rectangle.perimeter(), 2 * (10 + 4)); 40 | 41 | -------------------------------------------------------------------------------- /exercise/dmerge/2.ts: -------------------------------------------------------------------------------- 1 | // You are developing a system to manage vehicles in a fleet. The system needs 2 | // to handle different types of vehicles, such as cars and trucks. You'll use 3 | // declaration merging to extend the Vehicle interface to include additional 4 | // properties and methods specific to each vehicle type. 5 | // 6 | // Requirements: 7 | // - Define an initial interface Vehicle with the following properties: 8 | // - make: A string representing the vehicle's make (e.g., "Honda"). 9 | // - model: A string representing the vehicle's model (e.g., "Civic"). 10 | // - year: A number representing the year of manufacture. 11 | // - Use declaration merging to extend the Vehicle interface for Car with 12 | // additional properties: 13 | // - numberOfDoors: A number representing the number of doors on the car. 14 | // - hasSunroof: A boolean indicating whether the car has a sunroof. 15 | // - Use declaration merging to extend the Vehicle interface for Truck with 16 | // additional properties: 17 | // - payloadCapacity: A number representing the payload capacity in kilograms. 18 | // - numberOfAxles: A number representing the number of axles on the truck. 19 | // - Create instances of Car and Truck, set all properties to any values you'd 20 | // like, and print their details including the new properties. 21 | // - Only print the new properties if they are not null. 22 | 23 | 24 | -------------------------------------------------------------------------------- /exercise/dmerge/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/exceptions/1.ts: -------------------------------------------------------------------------------- 1 | // Your task is to create a class that only allows text input up to a certain 2 | // length. This length-restricted class will be used to ensure that users do 3 | // not enter too much information into an input field. 4 | // 5 | // Requirements: 6 | // - Create a class containing a length-limited string 7 | // - The class should not allow instantiation with strings greater than the 8 | // specified length 9 | // - The class should allow setting the maximum string length 10 | // - Throw an exception in the constructor of the class if the string is over 11 | // the maximum length 12 | 13 | import { strict as assert } from "assert"; 14 | 15 | 16 | -------------------------------------------------------------------------------- /exercise/exceptions/2.ts: -------------------------------------------------------------------------------- 1 | // You are building a application to manage a list of items. The application 2 | // needs to handle cases where an item is not found or invalid data is 3 | // provided. You'll use exceptions to manage these error conditions and ensure 4 | // that the application can respond appropriately. 5 | // 6 | // Requirements: 7 | // - Define a class `ItemNotFoundError` that extends the built-in `Error` class. 8 | // This class should be used to represent errors when an item is not found. 9 | // - Implement a function `findItem` that searches for an item in a list of items 10 | // by its ID. If the item is not found, it should throw an `ItemNotFoundError`. 11 | // - Create some test cases to ensure that your functions handle exceptions 12 | // properly. Specifically, test: 13 | // - Throwing and catching an `ItemNotFoundError` when searching for a 14 | // non-existent item. 15 | 16 | import { strict as assert } from "assert"; 17 | 18 | // Item interface 19 | interface Item { 20 | id: number; 21 | name: string; 22 | } 23 | 24 | // 25 | // Create your `ItemNotFoundError` class here. 26 | // 27 | // Create your `findItem` function here. 28 | // 29 | 30 | // Test cases 31 | const items: Item[] = [ 32 | { id: 1, name: "Item1" }, 33 | { id: 2, name: "Item2" } 34 | ]; 35 | 36 | try { 37 | findItem(items, 3); 38 | } catch (error) { 39 | if (error instanceof ItemNotFoundError) { 40 | console.log(`Caught ItemNotFoundError: ${error.message}`); // Caught ItemNotFoundError: Item with ID 3 not found. 41 | } else { 42 | console.error(`Unexpected error: ${(error as Error).message}`); 43 | } 44 | } 45 | 46 | const item1 = findItem(items, 1); 47 | assert.deepEqual(item1, { id: 1, name: "Item1" }); 48 | 49 | -------------------------------------------------------------------------------- /exercise/exceptions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/functions/1.ts: -------------------------------------------------------------------------------- 1 | // Using functions and template literals, print out your first and last name. 2 | // 3 | // Requirements: 4 | // - Use a single function to generate your first name 5 | // - Use a single function to generate your last name 6 | // - Use a single function to generate your full name by using the other 7 | // functions 8 | // - Print out your full name using the functions 9 | 10 | import { strict as assert } from "assert"; 11 | 12 | 13 | -------------------------------------------------------------------------------- /exercise/functions/2.ts: -------------------------------------------------------------------------------- 1 | // You are developing a application to manage a set of basic operations related 2 | // to geometric shapes. The application should be able to calculate the area of 3 | // a rectangle, the perimeter of a rectangle, and the area of a circle. You'll 4 | // implement these functions and demonstrate their usage. 5 | // 6 | // Requirements: 7 | // - Define a function named `calculateRectangleArea` that calculates the area 8 | // of a rectangle by returning the `width` multiplied by the `height`. 9 | // - Define a function named `calculateRectanglePerimeter` that calculates the 10 | // perimeter of a rectangle by returning the `width + height` and multiplying 11 | // it by 2 12 | // - Define a function named `calculateCircleArea` that calculates the area of 13 | // a circle by taking π (pi) as approximately 3.14 and multiplying it by the 14 | // `radius` times `radius`. 15 | // - Use these functions to perform some sample calculations and print the 16 | // results. 17 | 18 | import { strict as assert } from "assert"; 19 | 20 | 21 | // 22 | // Test cases 23 | assert.equal(calculateRectangleArea(5, 10), 50); 24 | assert.equal(calculateRectanglePerimeter(5, 10), 30); 25 | assert.equal(calculateCircleArea(7), 153.86); 26 | 27 | -------------------------------------------------------------------------------- /exercise/functions/3.ts: -------------------------------------------------------------------------------- 1 | // You are developing a application to manage basic mathematical operations on 2 | // three numbers. The application needs to calculate the average of three 3 | // numbers and then determine if the average is above a certain threshold. 4 | // 5 | // Requirements: 6 | // - Define a function named `calculateAverage` that takes three numbers and 7 | // returns their average. 8 | // - This function should call a helper function named `sum` to calculate the 9 | // total sum of the three numbers. 10 | // - The average is the calculated by adding all input values together and 11 | // then dividing it by the number of input values 12 | // - Define a function named `isAboveThreshold` that takes the average and a 13 | // threshold value and returns `true` if the average is greater than the 14 | // threshold, and `false` otherwise. 15 | // - Use these functions to perform some calculations and print whether the 16 | // average is above a given threshold. 17 | 18 | /* eslint-disable */ 19 | 20 | import { strict as assert } from "assert"; 21 | 22 | 23 | // 24 | // Test cases 25 | assert.equal(calculateAverage(10, 20, 30), 20); 26 | assert.equal(isAboveThreshold(20, 15), true); 27 | 28 | 29 | -------------------------------------------------------------------------------- /exercise/functions/4.ts: -------------------------------------------------------------------------------- 1 | // You are developing a application to determine whether a user is eligible for 2 | // a discount. 3 | // 4 | // Requirements: 5 | // 6 | // - Create two functions to check for discount eligibility: 7 | // 1. `isSenior`: returns `true` when the input `age` is 65 or older 8 | // 2. `isLargePurchase`: returns `true` when the input `amount` is over 99 9 | // - Define a function named `isEligibleForDiscount` and then use both the 10 | // `isSenior` and `isLargePurchase` functions that you created to determine 11 | // if there is discount eligibility. 12 | // - Use boolean logic and compound boolean operators to return `true` or 13 | // `false` from this function. 14 | // - Print out whether a user is eligible for a discount. 15 | 16 | /* eslint-disable */ 17 | 18 | import { strict as assert } from "assert"; 19 | 20 | 21 | // 22 | // Test cases 23 | assert.equal(isEligibleForDiscount(60, 90), false); 24 | assert.equal(isEligibleForDiscount(70, 90), true); 25 | assert.equal(isEligibleForDiscount(60, 100), true); 26 | 27 | -------------------------------------------------------------------------------- /exercise/functions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/generic-class/1.ts: -------------------------------------------------------------------------------- 1 | // Create a queue class that allows items to be placed into the queue and 2 | // removed from the queue. The queue must be generic over all types which 3 | // permits any type of data to be placed into the queue. 4 | // 5 | // The queue requires the following: 6 | // - Ability to add items to the queue 7 | // - Ability to remove items to the queue 8 | // - FIFO ordering. The first item added is the first item removed. 9 | // - Functionality to view all items that exist in the queue 10 | // 11 | // To confirm that your queue works properly, perform these steps: 12 | // 1. Create a queue over the string type 13 | // 2. Add "Hello" to the queue 14 | // 3. Add "World" to the queue 15 | // 4. Take the next item out of the queue 16 | // 5. Assert that the item is the string "Hello" 17 | // 6. View all items in the queue 18 | // 7. Assert that only "World" remains in the queue 19 | 20 | import { strict as assert } from "assert"; 21 | 22 | -------------------------------------------------------------------------------- /exercise/generic-class/2.ts: -------------------------------------------------------------------------------- 1 | // You are tasked with creating a program for storing and retrieving 2 | // information about books for use in a library system. 3 | // 4 | // Requirements: 5 | // - Create a generic class which can contain any type 6 | // - The class must have the following functionality: 7 | // - Set initial books from an array of existing books 8 | // - Add new books 9 | // - Remove existing books 10 | // - Viewing all books 11 | // - Viewing a subset of books based on a filter function 12 | // 13 | // To confirm that your program has the correct behavior, perform the following: 14 | // - Create a new generic collection of books from the existing `libraryBooks` 15 | // array 16 | // - Add `book3` to your collection 17 | // - Assert that the total number of books in the collection is 3 18 | // - Remove `book1` from the collection 19 | // - Assert that the total number of books in the collection is 2 20 | // - Retrieve all books written in the year 2023 or later 21 | // - Assert that the total number of books retrieved is 1 22 | 23 | import { strict as assert } from "assert"; 24 | 25 | interface Book { 26 | title: string; 27 | author: string; 28 | year: number; 29 | } 30 | 31 | const book1 = { title: "Book 1", author: "Author 1", year: 2021 }; 32 | const book2 = { title: "Book 2", author: "Author 2", year: 2022 }; 33 | const book3 = { title: "Book 3", author: "Author 3", year: 2023 }; 34 | const libraryBooks = [book1, book2]; 35 | 36 | 37 | -------------------------------------------------------------------------------- /exercise/generic-class/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/generic-function/1.ts: -------------------------------------------------------------------------------- 1 | // Write a generic function that can locate the first occurrence of an item in 2 | // an array. The function should accept an array of any type as a parameter, 3 | // along with an element to locate. If the element is found in the array, then 4 | // the function should return the index of where that element exists in the 5 | // array. If the element does not exist in the array, then the function should 6 | // return `undefined`. 7 | // 8 | // To test that your function works properly, perform these steps: 9 | // 1. Run your function with the existing `numbers` array and try to find the element 3 10 | // 2. Assert that the index returned is 2 11 | // 3. Run your function with the existing `numbers` array and try to find the element 6 12 | // 4. Assert that your function returns `undefined` 13 | 14 | import { strict as assert } from "assert"; 15 | 16 | const numbers: number[] = [1, 2, 3, 4, 5]; 17 | 18 | -------------------------------------------------------------------------------- /exercise/generic-function/2.ts: -------------------------------------------------------------------------------- 1 | // Write a generic function that can calculate the average of numbers in an 2 | // array. The function should operate on types that are compatible with 3 | // numbers, but should not work on non-numeric types, such as strings or 4 | // booleans. 5 | // 6 | // To calculate an average: 7 | // 1. Sum the numbers in the array 8 | // 2. Divide the sum by the number of elements 9 | // 10 | // To confirm that your program runs as expected: 11 | // 1. Run your function on the given `numbers` array 12 | // 2. Assert that the average is 3 13 | 14 | import { strict as assert } from "assert"; 15 | 16 | const numbers: number[] = [1, 2, 3, 4, 5]; 17 | 18 | -------------------------------------------------------------------------------- /exercise/generic-function/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/gradual-typing/1.ts: -------------------------------------------------------------------------------- 1 | // Convert the JavaScript program to a TypeScript program. See code comments 2 | // and assertions to help determine how the code is supposed to behave. For 3 | // more complex scenarios, consider using `console.log` to see the shape of an 4 | // object. This will help when creating interfaces and type aliases. 5 | // 6 | // Both the JavaScript and TypeScript code are shown here for comparison. In 7 | // practice you would not duplicate the code. 8 | 9 | import { strict as assert } from "assert"; 10 | 11 | function add(a, b) { 12 | return a + b; 13 | } 14 | 15 | console.log(add(5, 3)); 16 | assert.equal(add(1, 2), 3); 17 | 18 | // These don't crash, but they do not produce expected results. 19 | console.log(add("5", "3")); 20 | console.log(add(null, NaN)); 21 | console.log(add(0, "1")); 22 | console.log(add("1", 0)); 23 | console.log(add({}, 5)); 24 | console.log(add(2, [3])); 25 | console.log(add(2, () => 3)); 26 | 27 | -------------------------------------------------------------------------------- /exercise/gradual-typing/2.ts: -------------------------------------------------------------------------------- 1 | // Convert the JavaScript program to a TypeScript program. See code comments 2 | // and assertions to help determine how the code is supposed to behave. For 3 | // more complex scenarios, consider using `console.log` to see the shape of an 4 | // object. This will help when creating interfaces and type aliases. 5 | // 6 | // Both the JavaScript and TypeScript code are shown here for comparison. In 7 | // practice you would not duplicate the code. 8 | 9 | import { strict as assert } from "assert"; 10 | 11 | function calculate(operation, a, b) { 12 | if (operation === "add") { 13 | return a + b; 14 | } else if (operation === "subtract") { 15 | return a - b; 16 | } else if (operation === "multiply") { 17 | return a * b; 18 | } else if (operation === "divide") { 19 | return a / b; 20 | } else { 21 | return "Invalid operation"; 22 | } 23 | } 24 | 25 | console.log(calculate("add", 10, 5)); // Outputs: 15 26 | console.log(calculate("divide", 10, 2)); // Outputs: 5 27 | console.log(calculate("subtract", 10, 2)); // Outputs: 8 28 | 29 | console.log(calculate("whoops", 1, 2)); // Outputs: "Invalid operation" 30 | console.log(calculate("add", 2, "10")); // Outputs: "210" (unexpected behavior) 31 | 32 | assert.equal(calculate("add", 10, 5), 15) 33 | assert.equal(calculate("divide", 10, 2), 5) 34 | assert.equal(calculate("subtract", 10, 2), 8) 35 | 36 | -------------------------------------------------------------------------------- /exercise/gradual-typing/3.ts: -------------------------------------------------------------------------------- 1 | // Convert the JavaScript program to a TypeScript program. See code comments 2 | // and assertions to help determine how the code is supposed to behave. For 3 | // more complex scenarios, consider using `console.log` to see the shape of an 4 | // object. This will help when creating interfaces and type aliases. 5 | // 6 | // Both the JavaScript and TypeScript code are shown here for comparison. In 7 | // practice you would not duplicate the code. 8 | 9 | 10 | const assert = require("assert"); 11 | 12 | class Theater { 13 | constructor() { 14 | this.showtimes = {}; 15 | } 16 | 17 | addShowtime(movieTitle, showtime) { 18 | if (!this.showtimes[movieTitle]) { 19 | this.showtimes[movieTitle] = []; 20 | } 21 | this.showtimes[movieTitle].push(showtime); 22 | console.log(`Added showtime ${showtime} for movie "${movieTitle}".`); 23 | } 24 | 25 | removeShowtime(movieTitle, showtime) { 26 | if (this.showtimes[movieTitle]) { 27 | const index = this.showtimes[movieTitle].indexOf(showtime); 28 | if (index !== -1) { 29 | this.showtimes[movieTitle].splice(index, 1); 30 | console.log(`Removed showtime ${showtime} for movie "${movieTitle}".`); 31 | } else { 32 | console.log(`Showtime ${showtime} not found for movie "${movieTitle}".`); 33 | } 34 | } else { 35 | console.log(`Movie "${movieTitle}" not found.`); 36 | } 37 | } 38 | 39 | listShowtimes(movieTitle) { 40 | if (this.showtimes[movieTitle]) { 41 | console.log(`Showtimes for "${movieTitle}": ${this.showtimes[movieTitle].join(', ')}`); 42 | } else { 43 | console.log(`No showtimes found for movie "${movieTitle}".`); 44 | } 45 | } 46 | 47 | getShowtimes(movieTitle) { 48 | return this.showtimes[movieTitle]; 49 | } 50 | } 51 | 52 | // Example usage 53 | const theater = new Theater(); 54 | 55 | theater.addShowtime("The Matrix", "18:00"); 56 | theater.addShowtime("The Matrix", "21:00"); 57 | theater.addShowtime("Inception", "20:00"); 58 | 59 | theater.listShowtimes("The Matrix"); // Outputs: Showtimes for "The Matrix": 18:00, 21:00 60 | 61 | theater.removeShowtime("The Matrix", "18:00"); 62 | theater.listShowtimes("The Matrix"); // Outputs: Showtimes for "The Matrix": 21:00 63 | 64 | theater.addShowtime("Inception", "20:00"); 65 | 66 | // It's possible to add showtimes that aren't actual times, but this is not desired. 67 | theater.addShowtime("whoops", "whenever"); 68 | theater.listShowtimes("whoops"); // Outputs: Showtimes for "whoops": whenever 69 | 70 | // Test cases 71 | const testTheater = new Theater(); 72 | testTheater.addShowtime("a", "18:00"); 73 | testTheater.addShowtime("a", "21:00"); 74 | testTheater.addShowtime("b", "20:00"); 75 | testTheater.removeShowtime("a", "18:00"); 76 | assert.deepEqual(testTheater.getShowtimes("a"), ["21:00"]); 77 | assert.deepEqual(testTheater.getShowtimes("b"), ["20:00"]); 78 | 79 | -------------------------------------------------------------------------------- /exercise/gradual-typing/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/if-else/1.ts: -------------------------------------------------------------------------------- 1 | // == Part 1 == 2 | // 3 | // Write some code to allow or deny purchasing an item based on a given age. If 4 | // the purchaser is 18 years or older, then they are allowed to make the 5 | // purchase. If they are younger than 18 then they are not allowed to make the 6 | // purchase. 7 | // 8 | // To acknowledge if the person is allowed to make the purchase, print out "OK 9 | // to purchase". To acknowledge if the person is now allowed to make the 10 | // puchase, print out "cannot purchase". 11 | // 12 | // == Part 2 == 13 | // 14 | // Write some code that can determine if a person is an adult, child, 15 | // or senior: 16 | // - A person is a child if they are under 18 years old 17 | // - A person is an adult if they are at least 18 years old, and at most 64 18 | // years old 19 | // - A person is a senior if they are 65 years or older 20 | // 21 | // The code should exhibit this behavior: 22 | // - If the person is a child, then print "child" 23 | // - If the person is an adult, then print "adult" 24 | // - If the person is a senior, then print "senior" 25 | // 26 | // Check your code by changing the age to different values and confirm that the 27 | // correct messages are displayed. 28 | 29 | /* eslint-disable */ 30 | 31 | // Change this to different values to check your program behavior. 32 | const age = 25; 33 | 34 | 35 | -------------------------------------------------------------------------------- /exercise/if-else/2.ts: -------------------------------------------------------------------------------- 1 | // You are building a making application that helps determine whether a store 2 | // is open or closed based on the current time. The application will also check 3 | // if a user has sufficient funds to make a purchase. 4 | // 5 | // Requirements: 6 | // - Use an if-else statement to determine if the store is open. 7 | // - The store is open between 9 AM and 9 PM. 8 | // - Use 24-hour clock for time. So 4AM will be `400` and 10PM will be `2200` 9 | // - If the store is open, print "Store is open". If the store is closed, 10 | // print "Store is closed". 11 | // - Use another if-else statement to check if a user has enough money to make 12 | // a purchase. 13 | // - The user has enough money if their balance is greater than or equal to 14 | // the item price 15 | // - If the user has enough money to buy the item, print "Enough funds". If 16 | // not, print "Insufficient funds". 17 | // 18 | // Notes: 19 | // - Optionally use functions 20 | // - Change the initial constants to different values to check how your program 21 | // behaves. 22 | 23 | /* eslint-disable */ 24 | 25 | // Change this to different values to check your program behavior. 26 | const currentTime = 1000; // Example: 10 AM 27 | 28 | // 29 | // Put your code here to check if the store is open 30 | // 31 | 32 | // Change these to different values to check your program behavior. 33 | const userBalance = 50; 34 | const itemPrice = 40; 35 | 36 | // 37 | // Put your code here to check if the user has enough money to make a purchase 38 | // 39 | // 40 | -------------------------------------------------------------------------------- /exercise/if-else/3.ts: -------------------------------------------------------------------------------- 1 | // You are developing a weather advisory application that provides 2 | // recommendations based on the current temperature. The application will 3 | // suggest whether a user should wear a coat, bring an umbrella, or go out 4 | // without any weather-related gear. 5 | // 6 | // Requirements: 7 | // - Use an if-else statement to check the current temperature. 8 | // - If the temperature is below 10°C, print "It's cold, wear a coat." 9 | // - If the temperature is between 10°C and 20°C, print "Mild weather, bring 10 | // a light jacket." 11 | // - If the temperature is above 20°C, print "It's warm, no need for a 12 | // coat." 13 | // - Use another if-else statement to check if it's raining. 14 | // - If it is raining, print "Don't forget your umbrella!" 15 | // - If it's not raining, print "No umbrella needed." 16 | // 17 | // Notes: 18 | // - Optionally use functions 19 | // - Change the initial constants to different values to check how your program 20 | // behaves. 21 | 22 | /* eslint-disable */ 23 | 24 | // Change this to different values to check your program behavior. 25 | const temperature = 15; // Example: 15°C 26 | 27 | // 28 | // Put your code here to check the current temperature 29 | // 30 | 31 | // Change this to different values to check your program behavior. 32 | const isRaining = true; 33 | 34 | // 35 | // Put your code here to check if it's raining 36 | // 37 | // 38 | -------------------------------------------------------------------------------- /exercise/if-else/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/interfaces/1.ts: -------------------------------------------------------------------------------- 1 | // An amusement park operator is rolling out a new line-priority scheme where 2 | // people can get priority ride access based on their ticket. The operator 3 | // needs a program to determine if the person is allowed to use the priority 4 | // line based on various conditions. 5 | // 6 | // The park has these kinds of tickets: 7 | // - "Standard" 8 | // - "Premium" 9 | // - "Member" 10 | // - "VIP" 11 | // 12 | // Access to the priority line is governed by these rules: 13 | // - Standard tickets get no priority access 14 | // - Premium tickets can access the priority line only on weekdays 15 | // - Member tickets can access the priority line on weekends and weekdays 16 | // - VIP tickets can access the priority line at any time 17 | // 18 | // The data provided as a `day` in the interface is: 19 | // - "weekday" for weekdays 20 | // - "weekend" for weekends 21 | // - "holidays" for holidays 22 | // 23 | // For each kind of ticket, create a class. Each class must implement the 24 | // `PriorityAccess` interface and adhere to the rules described above. 25 | // 26 | // To confirm that your code works, perform the following: 27 | // 1. Create a standard ticket and assert that it cannot access the priority 28 | // line 29 | // 2. Create a premium ticket and assert that it can only access the priority 30 | // line when the day is "weekday" 31 | // 3. Create a member ticket and assert that it can only access the priority 32 | // line when the day is "weekday" or "weekend" 33 | // 4. Create a VIP ticket and assert that it can always access the priority 34 | // line 35 | 36 | import { strict as assert } from "assert"; 37 | 38 | -------------------------------------------------------------------------------- /exercise/interfaces/2.ts: -------------------------------------------------------------------------------- 1 | // You are working on a system that manages different payment methods for an 2 | // online store. Each payment method has a different fee charged by the 3 | // provider. 4 | // 5 | // Requirements: 6 | // - Create a `PaymentMethod` interface with the following properties: 7 | // - `providerName`: a string representing the payment provider's name. 8 | // - `calculateFee`: a method that accepts an amount (as a number) and returns 9 | // a number representing the fee that will be charged if the transaction 10 | // occurs. 11 | // - Implement two different classes that implement the `PaymentMethod` interface: 12 | // - `CreditCardPayment` with a provider name of "Credit Card". 13 | // - This provider charges 0.5% of the transaction amount for a fee. 14 | // - `DebugCardPayment` with a provider name of "Debit Card". 15 | // - This provider charges a flat fee of 0.30 units. 16 | // - Create instances of both `CreditCardPayment` and `DebitCardPayment`. 17 | // - Print the fee for a payment of 100 using both payment methods. 18 | // 19 | // Notes: 20 | // - We are using "units" for the monetary amounts. Feel free to think in terms 21 | // of your local currency. 22 | 23 | import { strict as assert } from "assert"; 24 | 25 | type Fee = number; 26 | 27 | // 28 | // Write your code here 29 | // 30 | 31 | // Test cases 32 | assert.equal(new CreditCardPayment().calculateFee(100), 0.5); 33 | assert.equal(new DebitCardPayment().calculateFee(100), 0.30); 34 | 35 | -------------------------------------------------------------------------------- /exercise/interfaces/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/iterators/1.ts: -------------------------------------------------------------------------------- 1 | // You are tasked with managing a list of products in an e-commerce 2 | // application. Each product has a name and a price. You need to iterate over 3 | // the list of products and print out their details. 4 | // 5 | // Requirements: 6 | // - Use a for..of loop to iterate over the array of products. 7 | // - Inside the loop, print out the name and price of each product in the 8 | // format: "Product: {name}, Price: ${price}". 9 | 10 | 11 | const products = [ 12 | { name: "Laptop", price: 999.99 }, 13 | { name: "Smartphone", price: 499.99 }, 14 | { name: "Tablet", price: 299.99 }, 15 | { name: "Headphones", price: 99.99 }, 16 | ]; 17 | 18 | 19 | // Expected Output: 20 | // Product: Laptop, Price: $999.99 21 | // Product: Smartphone, Price: $499.99 22 | // Product: Tablet, Price: $299.99 23 | // Product: Headphones, Price: $99.99 24 | // 25 | -------------------------------------------------------------------------------- /exercise/iterators/2.ts: -------------------------------------------------------------------------------- 1 | // You are developing a system to manage a list of tasks for a project 2 | // management application. Each task has a title and a status indicating 3 | // whether it is complete or incomplete. You need to iterate over the list of 4 | // tasks and print out the tasks that are incomplete. 5 | // 6 | // Requirements: 7 | // - Use a for..of loop to iterate over the array of tasks. 8 | // - Inside the loop, print out the title of each task that is incomplete, in 9 | // the format: "Incomplete Task: {title}". 10 | 11 | const tasks = [ 12 | { title: "Write project proposal", completed: true }, 13 | { title: "Design UI mockups", completed: false }, 14 | { title: "Develop backend API", completed: false }, 15 | { title: "Test application", completed: true }, 16 | { title: "Deploy to production", completed: false }, 17 | ]; 18 | 19 | 20 | // Expected Output: 21 | // Incomplete Task: Design UI mockups 22 | // Incomplete Task: Develop backend API 23 | // Incomplete Task: Deploy to production 24 | // 25 | -------------------------------------------------------------------------------- /exercise/iterators/3.ts: -------------------------------------------------------------------------------- 1 | // You are working on an inventory management system that keeps track of items 2 | // in a warehouse. Each item has various properties, such as its name, 3 | // quantity, and location. You need to iterate over the properties of an item 4 | // object and print out the details. 5 | // 6 | // Requirements: 7 | // - Use a for..in loop to iterate over the properties of the item object. 8 | // - Inside the loop, print out each property and its corresponding value in 9 | // the format: "{property}: {value}". 10 | 11 | const item = { 12 | name: "Laptop", 13 | quantity: 25, 14 | location: "Aisle 3, Shelf 2", 15 | }; 16 | 17 | 18 | // Expected Output: 19 | // name: Laptop 20 | // quantity: 25 21 | // location: Aisle 3, Shelf 2 22 | 23 | 24 | -------------------------------------------------------------------------------- /exercise/iterators/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/maps/1.ts: -------------------------------------------------------------------------------- 1 | // You are working on some software for use in a time clock where employees can 2 | // "punch in" and "punch out" to log the times when they come and go from their 3 | // job. Your task involves searching the database for the correct employee to 4 | // mark when they come and go. There can be upwards of thousands of employees 5 | // at any given employer and employees use an ID number to punch in and out. 6 | // Since there can be a large number of employees, searching through an array 7 | // is too slow and employees don't want to waste time waiting for their punch 8 | // to be confirmed. 9 | // 10 | // Requirements: 11 | // - Create a class that contains a map of employee ID numbers to employee 12 | // names. 13 | // - Populate the class with the provided employee information. 14 | // - Write functionality to check if the given employee ID matches an employee 15 | // in the map. This should return a simple true/false: true if the employee 16 | // with the given ID was found, and false if the employee ID was not found 17 | // 18 | // To test your code: 19 | // 1. Instantiate the class with the given employee data 20 | // 2. Assert that an employee with ID 17 exists 21 | // 3. Assert that an employee with ID 99 does not exist 22 | 23 | import { strict as assert } from "assert"; 24 | 25 | type EmployeeId = number; 26 | type EmployeeName = string; 27 | 28 | interface Employee { 29 | id: EmployeeId; 30 | name: EmployeeName; 31 | } 32 | 33 | const employees = [ 34 | { id: 1, name: "Alexander" }, 35 | { id: 2, name: "Amelia" }, 36 | { id: 3, name: "Ava" }, 37 | { id: 4, name: "Benjamin" }, 38 | { id: 5, name: "Charlotte" }, 39 | { id: 6, name: "Daniel" }, 40 | { id: 7, name: "Emily" }, 41 | { id: 8, name: "Emma" }, 42 | { id: 9, name: "Ethan" }, 43 | { id: 10, name: "Harper" }, 44 | { id: 11, name: "Isabella" }, 45 | { id: 12, name: "James" }, 46 | { id: 13, name: "Liam" }, 47 | { id: 14, name: "Matthew" }, 48 | { id: 15, name: "Mia" }, 49 | { id: 16, name: "Noah" }, 50 | { id: 17, name: "Olivia" }, 51 | { id: 18, name: "Samuel" }, 52 | { id: 19, name: "Sophia" }, 53 | { id: 20, name: "William" }, 54 | ]; 55 | 56 | 57 | -------------------------------------------------------------------------------- /exercise/maps/2.ts: -------------------------------------------------------------------------------- 1 | // You are developing a simple application to track the population of various 2 | // cities. Each city will be mapped to its population, allowing you to easily 3 | // update and retrieve the population data as needed. Your task is to implement 4 | // this using a Map in TypeScript. 5 | // 6 | // Requirements: 7 | // - Create a `Map` that maps city names (strings) to their population (numbers). 8 | // - Add at least three cities and their respective populations to the `Map`. 9 | // - Retrieve and print the population of a specific city. 10 | // - Update the population of a city. 11 | // - Print out all cities and their populations using a for..of loop. 12 | // 13 | // Notes: 14 | // - Use any city and population count, fictional or otherwise. 15 | 16 | /* eslint-disable */ 17 | 18 | 19 | -------------------------------------------------------------------------------- /exercise/maps/3.ts: -------------------------------------------------------------------------------- 1 | // You are developing a car rental system where each car is identified by its 2 | // license plate number. The system should track the availability of cars in 3 | // the rental fleet. Implement this system using a `Map` within a class. 4 | // 5 | // Requirements: 6 | // - Create a `CarRental` class that uses a `Map` to store cars. 7 | // - Each car should be represented by an object containing the car model 8 | // (string) and its availability status (boolean). 9 | // - Implement the following functions for the class: 10 | // - `addCar`: adds a new car to the rental fleet 11 | // - adding a car requires a license plate (string), model, and availability status 12 | // - `updateAvailability`: changes the status of a car (whether it's rented 13 | // or returned). This method must return `true` if the status was changed, 14 | // and `false` otherwise. 15 | // - `getCar`: searches for a car by license plate number and returns a `Car | undefined` 16 | // - `printAllCars: print out all cars and their details 17 | 18 | import { strict as assert } from "assert"; 19 | 20 | interface Car { 21 | model: string; 22 | isAvailable: boolean; 23 | } 24 | 25 | // 26 | // Add your code here 27 | // 28 | 29 | // Test cases: 30 | const testRental = new CarRental(); 31 | testRental.addCar("test1", "car1", true); 32 | testRental.addCar("test2", "car2", true); 33 | testRental.updateAvailability("test1", false); 34 | assert.equal(testRental.updateAvailability("unknown plate", false), false); 35 | assert.equal(testRental.getCar("test1")?.isAvailable, false); 36 | assert.equal(testRental.getCar("test2")?.isAvailable, true); 37 | 38 | 39 | -------------------------------------------------------------------------------- /exercise/maps/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/optional-chaining/1.ts: -------------------------------------------------------------------------------- 1 | // Using optional chaining, print the price amount of each listed product. If 2 | // there is no price amount, then print "not for sale". 3 | 4 | import { strict as assert } from "assert"; 5 | 6 | interface Product { 7 | name: string; 8 | price?: { 9 | amount: number; 10 | currency: string; 11 | }; 12 | } 13 | 14 | const phone: Product = { 15 | name: "Phone", 16 | price: { 17 | amount: 300, 18 | currency: "USD" 19 | } 20 | }; 21 | 22 | const box: Product = { 23 | name: "Box" 24 | }; 25 | 26 | 27 | -------------------------------------------------------------------------------- /exercise/optional-chaining/2.ts: -------------------------------------------------------------------------------- 1 | // You are building a system for managing book reviews in an online bookstore. 2 | // Each book has a review section that may contain nested data about reviewer 3 | // comments, ratings, and review details. Implement a way to safely access 4 | // these nested properties using optional chaining. 5 | // 6 | // Requirements: 7 | // - Use optional chaining to access various properties of the `bookReview` object. 8 | // 9 | // Notes: 10 | // - The property to access is detailed in the code comments. 11 | 12 | import { strict as assert } from "assert"; 13 | 14 | interface Review { 15 | reviewer?: { 16 | name?: string; 17 | age?: number; 18 | }; 19 | rating?: number; 20 | details?: { 21 | comment?: string; 22 | date?: string; 23 | }; 24 | } 25 | 26 | interface BookReview { 27 | title: string; 28 | reviews?: Review[]; 29 | } 30 | 31 | const bookReview: BookReview = { 32 | title: "The Great Adventure", 33 | reviews: [ 34 | { 35 | reviewer: { 36 | name: "John Doe", 37 | age: 30 38 | }, 39 | rating: 4, 40 | details: { 41 | comment: "An amazing book!", 42 | date: "2024-08-10" 43 | } 44 | }, 45 | { 46 | reviewer: { 47 | name: "Jane Smith" 48 | }, 49 | rating: 5 50 | } 51 | ] 52 | }; 53 | 54 | // Access the first reviewer's name 55 | assert.equal(firstReviewerName, "John Doe"); 56 | 57 | // Access the first reviewer's age 58 | assert.equal(firstReviewerAge, 30); 59 | 60 | // Access the rating of the second review 61 | assert.equal(secondReviewRating, 5); 62 | 63 | // Access the comment of the second review (does not exist) 64 | assert.equal(secondReviewComment, undefined); 65 | 66 | // Access the date of the first review 67 | assert.equal(firstReviewDate, "2024-08-10"); 68 | 69 | -------------------------------------------------------------------------------- /exercise/optional-chaining/3.ts: -------------------------------------------------------------------------------- 1 | // You are developing a customer support system where each customer has an 2 | // account that may contain nested information such as support tickets and 3 | // ticket details. Implement a function to retrieve ticket comments safely 4 | // using optional chaining. 5 | // 6 | // Requirements: 7 | // - Implement a function called `getTicketComments` that: 8 | // - Takes a `CustomerAccount` object and a `ticketId` as parameters. 9 | // - Uses optional chaining to safely retrieve and return the array of 10 | // comments for the given ticket ID. 11 | // - If the ticket or comments do not exist, return an empty array. 12 | 13 | import { strict as assert } from "assert"; 14 | 15 | interface SupportTicket { 16 | ticketId: string; 17 | details?: { 18 | comments?: string[]; 19 | }; 20 | } 21 | interface CustomerAccount { 22 | name: string; 23 | supportTickets?: SupportTicket[]; 24 | } 25 | 26 | 27 | // 28 | // Write your function here 29 | // 30 | 31 | 32 | // Test cases 33 | const testAccount: CustomerAccount = { 34 | name: "Alice Johnson", 35 | supportTickets: [ 36 | { 37 | ticketId: "T123", 38 | details: { 39 | comments: ["Comment 1", "Comment 2"] 40 | } 41 | }, 42 | { 43 | ticketId: "T456", 44 | details: { 45 | comments: ["Comment A"] 46 | } 47 | } 48 | ] 49 | }; 50 | const commentsT123 = getTicketComments(testAccount, "T123"); 51 | assert.deepStrictEqual(commentsT123, ["Comment 1", "Comment 2"]); 52 | 53 | const commentsT456 = getTicketComments(testAccount, "T456"); 54 | assert.deepStrictEqual(commentsT456, ["Comment A"]); 55 | 56 | // Test 3: Retrieve comments for a non-existent ticket 57 | const commentsT999 = getTicketComments(testAccount, "T999"); 58 | assert.deepStrictEqual(commentsT999, []); 59 | 60 | // Test 4: Retrieve comments when no supportTickets are available 61 | const emptyAccount: CustomerAccount = { name: "Bob Smith" }; 62 | const commentsEmpty = getTicketComments(emptyAccount, "T123"); 63 | assert.deepStrictEqual(commentsEmpty, []); 64 | 65 | 66 | -------------------------------------------------------------------------------- /exercise/optional-chaining/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/repetition-for/1.ts: -------------------------------------------------------------------------------- 1 | // Using the provided scores in the array, calculate the average score. 2 | // 3 | // To calculate an average: 4 | // 1. Sum the numbers in the array 5 | // 2. Divide the sum by the number of elements 6 | // 7 | // To confirm that your code works as expected, perform the following steps: 8 | // 1. Calculate the average of the `scores` array 9 | // 2. Assert that the average is 85 10 | // 3. Push 92 onto the `scores` array 11 | // 4. Calculate the average again 12 | // 5. Assert that the average is now 86 13 | import { strict as assert } from "assert"; 14 | 15 | const scores = [90, 77, 83, 96, 76, 88]; 16 | 17 | 18 | -------------------------------------------------------------------------------- /exercise/repetition-for/2.ts: -------------------------------------------------------------------------------- 1 | // Implement a sorting algorithm of your choosing to sort the provided array. 2 | // Good introductory sorting algorithms are bubble sort and insertion sort. 3 | // 4 | // To confirm that your algorithm works properly, perform these steps: 5 | // 1. Run your sorting algorithm on the `nums` array 6 | // 2. Assert that the sorted array is [1, 2, 3, 4, 5] 7 | // 8 | import { strict as assert } from "assert"; 9 | 10 | const nums = [5, 4, 3, 2, 1]; 11 | 12 | 13 | -------------------------------------------------------------------------------- /exercise/repetition-for/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/repetition-while/1.ts: -------------------------------------------------------------------------------- 1 | // You are tasked with writing a program to calculate the total amount of time 2 | // a user has spent on a web page. An array is provided containing data for 3 | // each user and the duration of each visit in the `durations` array. 4 | // 5 | // Requirements: 6 | // - Use the provided data to sum the values in the `durations` array for each 7 | // user 8 | // - Take the sum and update the existing `users` array by setting the `total` 9 | // value to the calculated sum 10 | // - Use at least 1 while loop in your code 11 | 12 | import { strict as assert } from "assert"; 13 | 14 | const users = [ 15 | { id: 1, durations: [30, 16, 9], total: 0 }, 16 | { id: 2, durations: [12, 31, 35], total: 0 }, 17 | { id: 3, durations: [10, 34, 36], total: 0 }, 18 | { id: 4, durations: [45, 36, 14], total: 0 }, 19 | { id: 5, durations: [22, 12, 24], total: 0 }, 20 | { id: 6, durations: [19, 11, 33], total: 0 }, 21 | ]; 22 | 23 | assert.deepStrictEqual(users, [ 24 | { id: 1, durations: [30, 16, 9], total: 55 }, 25 | { id: 2, durations: [12, 31, 35], total: 78 }, 26 | { id: 3, durations: [10, 34, 36], total: 80 }, 27 | { id: 4, durations: [45, 36, 14], total: 95 }, 28 | { id: 5, durations: [22, 12, 24], total: 58 }, 29 | { id: 6, durations: [19, 11, 33], total: 63 }, 30 | ]); 31 | 32 | -------------------------------------------------------------------------------- /exercise/repetition-while/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/switch/1.ts: -------------------------------------------------------------------------------- 1 | // You are working on a program to classify certain weights into a weight class 2 | // for competition. Certain weight classes are allowed to compete against 3 | // similar weight classes. There is a tiered system in place and when a 4 | // competitor reaches the next tier, then they get placed in the next weight 5 | // class. 6 | // 7 | // Write a program using a `switch` statement that fulfills the following: 8 | // - When the weight class is 1, 2, or 3, print the text "light weight class" 9 | // - When the weight class is 4, 5, or 6, print the text "medium weight class" 10 | // - When the weight class is 7, 8, 9, or 10, print the text "heavy weight 11 | // class" 12 | // 13 | // Modify the existing `weightClass` variable to confirm that your code works 14 | // as expected. 15 | 16 | import { strict as assert } from "assert"; 17 | 18 | const weightClass = parseInt("3"); 19 | 20 | 21 | -------------------------------------------------------------------------------- /exercise/switch/2.ts: -------------------------------------------------------------------------------- 1 | // You are building a simple menu system for a text-based application. 2 | // Implement a function that uses a switch statement to handle different menu 3 | // options based on user input. 4 | // 5 | // Requirements: 6 | // - Create a function called `handleMenuSelection` that: 7 | // - Takes a number representing the user's menu option choice. 8 | // - Uses a switch statement to handle the following menu options: 9 | // - 1: Print "Option 1 selected." 10 | // - 2: Print "Option 2 selected." 11 | // - 3: Print "Option 3 selected." 12 | // - 4: Print "Option 4 selected." 13 | // - Ensure the function handles invalid options gracefully by printing 14 | // "Invalid option selected" if any number other than 1, 2, 3, 4 are selected 15 | 16 | 17 | // Test cases 18 | handleMenuSelection(1); // Output: Option 1 selected. 19 | handleMenuSelection(2); // Output: Option 2 selected. 20 | handleMenuSelection(3); // Output: Option 3 selected. 21 | handleMenuSelection(4); // Output: Option 4 selected. 22 | handleMenuSelection(5); // Output: Invalid option selected. 23 | 24 | -------------------------------------------------------------------------------- /exercise/switch/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/ternary/1.ts: -------------------------------------------------------------------------------- 1 | // Using at least one ternary operator, create a program that can convert 2 | // Celsius and Fahrenheit temperatures. 3 | // 4 | // To convert °C to °F: (°C * 1.8) + 32 5 | // To convert °F to °C: (°F - 32) / 1.8 6 | // 7 | // To confirm that your program works properly, do the following: 8 | // 1. convert 25°C to °F, and assert that the value is 77 9 | // 1. convert 68°F to °C, and assert that the value is 20 10 | 11 | import { strict as assert } from "assert"; 12 | 13 | 14 | -------------------------------------------------------------------------------- /exercise/ternary/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /exercise/type-predicates/1.ts: -------------------------------------------------------------------------------- 1 | // You are developing a system that processes user inputs, where each input 2 | // could be a string or a number. Implement a function that uses type 3 | // predicates to determine the type of input and perform type-specific 4 | // processing. 5 | // 6 | // Requirements: 7 | // - Create a function called `processInput` that: 8 | // - Takes input, which can be either a string or a number. 9 | // - Uses a type predicate to check if the input is a string or a number. 10 | // - For a string, print "Processing string: " followed by the string. 11 | // - For a number, print "Processing number: " followed by the number. 12 | // - Ensure the type-specific processing is handled correctly. 13 | 14 | 15 | // Test cases 16 | processInput("Hello, world!"); // Output: Processing string: Hello, world! 17 | processInput(42); // Output: Processing number: 42 18 | processInput(""); // Output: Processing string: 19 | processInput(0); // Output: Processing number: 0 20 | 21 | -------------------------------------------------------------------------------- /exercise/unions/1.ts: -------------------------------------------------------------------------------- 1 | // You are working on a task management system where tasks can have different 2 | // statuses.Implement a function that logs a message based on the type of task 3 | // status, which can be either a string(status message) or a number(status 4 | // code). 5 | // 6 | // Requirements: 7 | // - Create a function called `logTaskStatus` that: 8 | // - Takes status, which can be either a `string` or a `number`. 9 | // - If status is a `string`, print "Task status message: " followed by the 10 | // status message. 11 | // - If status is a `number`, print "Task status code: " followed by the 12 | // status code. 13 | 14 | 15 | 16 | logTaskStatus("Completed"); // Output: Task status message: Completed 17 | logTaskStatus(200); // Output: Task status code: 200 18 | logTaskStatus("In Progress"); // Output: Task status message: In Progress 19 | logTaskStatus(404); // Output: Task status code: 404 20 | 21 | -------------------------------------------------------------------------------- /exercise/unions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": {} 4 | } 5 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * For a detailed explanation regarding each configuration property and type check, visit: 3 | * https://jestjs.io/docs/configuration 4 | */ 5 | 6 | module.exports = { 7 | preset: 'ts-jest', 8 | testEnvironment: 'node', 9 | // All imported modules in your tests should be mocked automatically 10 | // automock: false, 11 | 12 | // Stop running tests after `n` failures 13 | // bail: 0, 14 | 15 | // The directory where Jest should store its cached dependency information 16 | // cacheDirectory: "/tmp/jest_rs", 17 | 18 | // Automatically clear mock calls, instances, contexts and results before every test 19 | clearMocks: true, 20 | 21 | // Indicates whether the coverage information should be collected while executing the test 22 | collectCoverage: true, 23 | 24 | // An array of glob patterns indicating a set of files for which coverage information should be collected 25 | // collectCoverageFrom: undefined, 26 | 27 | // The directory where Jest should output its coverage files 28 | coverageDirectory: "coverage", 29 | 30 | // An array of regexp pattern strings used to skip coverage collection 31 | coveragePathIgnorePatterns: [ 32 | "/node_modules/", 33 | ], 34 | 35 | // Indicates which provider should be used to instrument code for coverage 36 | coverageProvider: "v8", 37 | 38 | // A list of reporter names that Jest uses when writing coverage reports 39 | // coverageReporters: [ 40 | // "json", 41 | // "text", 42 | // "lcov", 43 | // "clover" 44 | // ], 45 | 46 | // An object that configures minimum threshold enforcement for coverage results 47 | // coverageThreshold: undefined, 48 | 49 | // A path to a custom dependency extractor 50 | // dependencyExtractor: undefined, 51 | 52 | // Make calling deprecated APIs throw helpful error messages 53 | // errorOnDeprecated: false, 54 | 55 | // The default configuration for fake timers 56 | // fakeTimers: { 57 | // "enableGlobally": false 58 | // }, 59 | 60 | // Force coverage collection from ignored files using an array of glob patterns 61 | // forceCoverageMatch: [], 62 | 63 | // A path to a module which exports an async function that is triggered once before all test suites 64 | // globalSetup: undefined, 65 | 66 | // A path to a module which exports an async function that is triggered once after all test suites 67 | // globalTeardown: undefined, 68 | 69 | // A set of global variables that need to be available in all test environments 70 | // globals: {}, 71 | 72 | // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. 73 | // maxWorkers: "50%", 74 | 75 | // An array of directory names to be searched recursively up from the requiring module's location 76 | // moduleDirectories: [ 77 | // "node_modules" 78 | // ], 79 | 80 | // An array of file extensions your modules use 81 | // moduleFileExtensions: [ 82 | // "js", 83 | // "mjs", 84 | // "cjs", 85 | // "jsx", 86 | // "ts", 87 | // "tsx", 88 | // "json", 89 | // "node" 90 | // ], 91 | 92 | // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module 93 | // moduleNameMapper: {}, 94 | 95 | // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader 96 | // modulePathIgnorePatterns: [], 97 | 98 | // Activates notifications for test results 99 | // notify: false, 100 | 101 | // An enum that specifies notification mode. Requires { notify: true } 102 | // notifyMode: "failure-change", 103 | 104 | // A preset that is used as a base for Jest's configuration 105 | // preset: undefined, 106 | 107 | // Run tests from one or more projects 108 | // projects: undefined, 109 | 110 | // Use this configuration option to add custom reporters to Jest 111 | // reporters: undefined, 112 | 113 | // Automatically reset mock state before every test 114 | // resetMocks: false, 115 | 116 | // Reset the module registry before running each individual test 117 | // resetModules: false, 118 | 119 | // A path to a custom resolver 120 | // resolver: undefined, 121 | 122 | // Automatically restore mock state and implementation before every test 123 | // restoreMocks: false, 124 | 125 | // The root directory that Jest should scan for tests and modules within 126 | // rootDir: undefined, 127 | 128 | // A list of paths to directories that Jest should use to search for files in 129 | // roots: [ 130 | // "" 131 | // ], 132 | 133 | // Allows you to use a custom runner instead of Jest's default test runner 134 | // runner: "jest-runner", 135 | 136 | // The paths to modules that run some code to configure or set up the testing environment before each test 137 | // setupFiles: [], 138 | 139 | // A list of paths to modules that run some code to configure or set up the testing framework before each test 140 | // setupFilesAfterEnv: [], 141 | 142 | // The number of seconds after which a test is considered as slow and reported as such in the results. 143 | // slowTestThreshold: 5, 144 | 145 | // A list of paths to snapshot serializer modules Jest should use for snapshot testing 146 | // snapshotSerializers: [], 147 | 148 | // The test environment that will be used for testing 149 | // testEnvironment: "jest-environment-node", 150 | 151 | // Options that will be passed to the testEnvironment 152 | // testEnvironmentOptions: {}, 153 | 154 | // Adds a location field to test results 155 | // testLocationInResults: false, 156 | 157 | // The glob patterns Jest uses to detect test files 158 | // testMatch: [ 159 | // "**/__tests__/**/*.[jt]s?(x)", 160 | // "**/?(*.)+(spec|test).[tj]s?(x)" 161 | // ], 162 | 163 | // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped 164 | // testPathIgnorePatterns: [ 165 | // "/node_modules/" 166 | // ], 167 | 168 | // The regexp pattern or array of patterns that Jest uses to detect test files 169 | // testRegex: [], 170 | 171 | // This option allows the use of a custom results processor 172 | // testResultsProcessor: undefined, 173 | 174 | // This option allows use of a custom test runner 175 | // testRunner: "jest-circus/runner", 176 | 177 | // A map from regular expressions to paths to transformers 178 | // transform: undefined, 179 | 180 | // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation 181 | // transformIgnorePatterns: [ 182 | // "/node_modules/", 183 | // "\\.pnp\\.[^\\/]+$" 184 | // ], 185 | 186 | // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them 187 | // unmockedModulePathPatterns: undefined, 188 | 189 | // Indicates whether each individual test should be reported during the run 190 | // verbose: undefined, 191 | 192 | // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode 193 | // watchPathIgnorePatterns: [], 194 | 195 | // Whether to use watchman for file crawling 196 | // watchman: true, 197 | }; 198 | 199 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ztm-typescript-course-content", 3 | "version": "0.1.0", 4 | "license": "(MIT OR Apache-2.0)", 5 | "private": true, 6 | "author": "Jayson Lennon ", 7 | "homepage": "https://zerotomastery.io/courses/learn-typescript", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/jayson-lennon/ztm-typescript" 11 | }, 12 | "scripts": { 13 | "run-demo": "ts-node", 14 | "test": "jest", 15 | "typecheck": "tsc --noEmit --strict -p", 16 | "lint": "eslint", 17 | "check": "node check.js" 18 | }, 19 | "devDependencies": { 20 | "@tsconfig/strictest": "^1.0.2", 21 | "@types/core-js": "^2.5.5", 22 | "@types/jest": "^29.5.1", 23 | "@types/node": "^18.16.3", 24 | "@typescript-eslint/eslint-plugin": "^5.59.2", 25 | "@typescript-eslint/parser": "^5.59.2", 26 | "autoprefixer": "^10.4.14", 27 | "eslint": "^8.39.0", 28 | "eslint-config-prettier": "^8.8.0", 29 | "eslint-config-standard-with-typescript": "^23.0.0", 30 | "eslint-plugin-import": "^2.27.5", 31 | "eslint-plugin-n": "^15.7.0", 32 | "eslint-plugin-promise": "^6.1.1", 33 | "jest": "^29.5.0", 34 | "ts-jest": "^29.1.0", 35 | "ts-node": "^10.9.1", 36 | "typescript": "^5.0.4" 37 | }, 38 | "engines": { 39 | "node": ">=18.9.1" 40 | }, 41 | "dependencies": {} 42 | } 43 | 44 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: ["./**/index.html", ".demo/**/*.{js,ts,jsx,tsx}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [ 8 | require("daisyui"), 9 | require("@tailwindcss/forms"), 10 | ], 11 | }; 12 | 13 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/strictest/tsconfig.json", 3 | "exclude": [ 4 | "**/dist" 5 | ], 6 | "compilerOptions": { 7 | // "allowImportingTsExtensions": true, 8 | /* Visit https://aka.ms/tsconfig to read more about this file */ 9 | /* Projects */ 10 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 11 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 12 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 13 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 14 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 15 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 16 | /* Language and Environment */ 17 | "target": "es2020" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, 18 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 19 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ 20 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 21 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 22 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 23 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 24 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 25 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 26 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 27 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 28 | /* Modules */ 29 | "module": "node16" /* Specify what module code is generated. */, 30 | // "rootDir": "./", /* Specify the root folder within your source files. */ 31 | // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ 32 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 33 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 34 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 35 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 36 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 37 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 38 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 39 | // "resolveJsonModule": true, /* Enable importing .json files. */ 40 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 41 | /* JavaScript Support */ 42 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 43 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 44 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 45 | /* Emit */ 46 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 47 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 48 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 49 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 50 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 51 | // "outDir": "./", /* Specify an output folder for all emitted files. */ 52 | // "removeComments": true, /* Disable emitting comments. */ 53 | // "noEmit": true, /* Disable emitting files from a compilation. */ 54 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 55 | "importsNotUsedAsValues": "remove" /* Specify emit/checking behavior for imports that are only used for types. */, 56 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 57 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 58 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 59 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 60 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 61 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 62 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 63 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 64 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 65 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 66 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 67 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 68 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 69 | /* Interop Constraints */ 70 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 71 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 72 | "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, 73 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 74 | "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, 75 | /* Type Checking */ 76 | "strict": true /* Enable all strict type-checking options. */, 77 | "noImplicitAny": false, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 78 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 79 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 80 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 81 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 82 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 83 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 84 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 85 | "noUnusedLocals": false /* Enable error reporting when local variables aren't read. */, 86 | "noUnusedParameters": false /* Raise an error when a function parameter isn't read. */, 87 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 88 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 89 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 90 | "noUncheckedIndexedAccess": false /* Add 'undefined' to a type when accessed using an index. */, 91 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 92 | "noPropertyAccessFromIndexSignature": false, /* Enforces using indexed accessors for keys declared using an indexed type. */ 93 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 94 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 95 | /* Completeness */ 96 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 97 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 98 | } 99 | } 100 | 101 | --------------------------------------------------------------------------------