├── .gitattributes ├── .gitignore ├── CONTRIBUTING.md ├── GLOSSARY.md ├── LICENSE.md ├── README.md ├── SUMMARY.md ├── book.json ├── code ├── async-await │ ├── es5 │ │ ├── asyncAwaitES5.js │ │ ├── asyncAwaitES5.ts │ │ └── tsconfig.json │ └── es6 │ │ ├── asyncAwaitES6.js │ │ ├── asyncAwaitES6.ts │ │ └── tsconfig.json ├── compiler │ ├── node_modules │ │ ├── .bin │ │ │ ├── ntsc │ │ │ ├── ntsc.cmd │ │ │ ├── ntse │ │ │ ├── ntse.cmd │ │ │ ├── ntsserver │ │ │ └── ntsserver.cmd │ │ └── ntypescript │ │ │ ├── .npmignore │ │ │ ├── .travis.yml │ │ │ ├── CONTRIBUTING.md │ │ │ ├── Gruntfile.js │ │ │ ├── LICENCE │ │ │ ├── README.md │ │ │ ├── appveyor.yml │ │ │ ├── bin │ │ │ ├── lib.core.d.ts │ │ │ ├── lib.core.es6.d.ts │ │ │ ├── lib.d.ts │ │ │ ├── lib.dom.d.ts │ │ │ ├── lib.es6.d.ts │ │ │ ├── lib.scriptHost.d.ts │ │ │ ├── lib.webworker.d.ts │ │ │ ├── ntypescript.d.ts │ │ │ ├── ntypescript.js │ │ │ ├── tsc │ │ │ ├── tsc.js │ │ │ ├── tse │ │ │ ├── tsserver │ │ │ ├── tsserver.js │ │ │ ├── typescript.d.ts │ │ │ ├── typescript.js │ │ │ ├── typescriptServices.d.ts │ │ │ └── typescriptServices.js │ │ │ ├── extensions │ │ │ ├── addExtensions.d.ts │ │ │ ├── addExtensions.js │ │ │ ├── addExtensions.ts │ │ │ ├── extensions.d.ts │ │ │ ├── extensions.js │ │ │ ├── extensions.ts │ │ │ └── tsconfig.json │ │ │ ├── kicktravis │ │ │ ├── package.json │ │ │ ├── prepare.sh │ │ │ ├── quick.sh │ │ │ ├── register.js │ │ │ ├── register.ts │ │ │ ├── release.sh │ │ │ ├── tasks │ │ │ ├── ntypescript.js │ │ │ └── ntypescript.ts │ │ │ ├── tsconfig.json │ │ │ ├── tsd.json │ │ │ ├── tse.js │ │ │ ├── tse.ts │ │ │ └── typings │ │ │ ├── gruntjs │ │ │ └── gruntjs.d.ts │ │ │ ├── node │ │ │ └── node.d.ts │ │ │ └── tsd.d.ts │ ├── package.json │ ├── parser │ │ ├── runParser.js │ │ └── runParser.ts │ ├── scanner │ │ ├── runScanner.js │ │ ├── runScanner.ts │ │ ├── runScannerWithPositions.js │ │ └── runScannerWithPositions.ts │ ├── tsconfig.json │ ├── tsd.json │ └── typings │ │ ├── node │ │ └── node.d.ts │ │ └── tsd.d.ts ├── declarationspaces │ ├── declarationspace.js │ └── declarationspace.ts ├── dynamic-import-expressions │ ├── dynamicImportExpression.js │ ├── dynamicImportExpression.ts │ ├── package.json │ └── tsconfig.json ├── errors │ ├── common-errors.ts │ ├── interpreting-errors.ts │ └── tsconfig.json ├── es6 │ ├── classes │ │ ├── abstract.js │ │ ├── abstract.ts │ │ ├── class.js │ │ ├── class.ts │ │ ├── super.js │ │ ├── super.ts │ │ └── tsconfig.json │ ├── const.js │ ├── const.ts │ ├── destructuring.js │ ├── destructuring.ts │ ├── enums.js │ ├── enums.ts │ ├── for..of.js │ ├── for..of.ts │ ├── forof.js │ ├── iterators.js │ ├── iterators.ts │ ├── let.js │ ├── let.ts │ ├── rest-parameters.js │ ├── rest-parameters.ts │ ├── spread-operator.js │ ├── spread-operator.ts │ ├── template-strings.js │ ├── template-strings.ts │ ├── test.js │ ├── test.ts │ └── tsconfig.json ├── javascript │ ├── closure.js │ ├── closure.ts │ └── tsconfig.json ├── tips │ ├── bindIsBad.js │ ├── bindIsBad.ts │ ├── currying.js │ ├── currying.ts │ ├── lazyObjectLiteralInitialization.js │ ├── lazyObjectLiteralInitialization.ts │ ├── mixins.js │ ├── mixins.ts │ ├── nominalTyping.js │ ├── nominalTyping.ts │ ├── statefulFunctions.js │ ├── statefulFunctions.ts │ ├── stringEnums.js │ ├── stringEnums.ts │ └── tsconfig.json └── types │ ├── assertion.js │ ├── assertion.ts │ ├── callable.ts │ ├── freshness │ ├── freshness.js │ ├── freshness.ts │ ├── index-signatures.js │ ├── index-signatures.ts │ └── tsconfig.json │ ├── functions.js │ ├── functions.ts │ ├── generics.js │ ├── generics.ts │ ├── interfaces.js │ ├── interfaces.ts │ ├── keyof.ts │ ├── lib │ ├── exclude │ │ ├── nolibd.js │ │ ├── nolibd.ts │ │ └── tsconfig.json │ └── usage │ │ ├── libd.js │ │ ├── libd.ts │ │ └── tsconfig.json │ ├── libd.js │ ├── literal-types.js │ ├── literal-types.ts │ ├── migrating │ ├── migrating.js │ ├── migrating.ts │ └── tsconfig.json │ ├── readonly.js │ ├── readonly.ts │ ├── stringLiteralType.js │ ├── tsconfig.json │ ├── type-compatibility.js │ ├── type-compatibility.ts │ ├── type-inference.js │ ├── type-inference.ts │ ├── typeGuard.js │ ├── typeGuard.ts │ ├── types.js │ └── types.ts ├── cover.jpg ├── docs ├── arrow-functions.md ├── async-await.md ├── classes-emit.md ├── classes.md ├── compiler-options.md ├── compiler │ ├── ast-tip-children.md │ ├── ast-tip-syntaxkind.md │ ├── ast-trivia.md │ ├── ast.md │ ├── binder-container.md │ ├── binder-declarations.md │ ├── binder-diagnostics.md │ ├── binder-functions.md │ ├── binder-symbolflags.md │ ├── binder-symboltable.md │ ├── binder.md │ ├── checker-diagnostics.md │ ├── checker-global.md │ ├── checker.md │ ├── contributing.md │ ├── emitter-functions.md │ ├── emitter-sourcemaps.md │ ├── emitter.md │ ├── make-global.md │ ├── overview.md │ ├── parser-functions.md │ ├── parser.md │ ├── program.md │ └── scanner.md ├── const.md ├── declaration.md ├── destructuring.md ├── enums.md ├── errors │ ├── common-errors.md │ ├── interpreting-errors.md │ └── main.md ├── for...of.md ├── future-javascript.md ├── generators.md ├── getting-started.md ├── iterators.md ├── javascript │ ├── closure.md │ ├── equality.md │ ├── null-undefined.md │ ├── number.md │ ├── recap.md │ ├── references.md │ ├── this.md │ └── truthy.md ├── jsx │ ├── others.md │ ├── react.md │ └── tsx.md ├── let.md ├── npm │ └── index.md ├── options │ ├── intro.md │ ├── noImplicitAny.md │ └── strictNullChecks.md ├── project │ ├── compilation-context.md │ ├── declarationspaces.md │ ├── dynamic-import-expressions.md │ ├── external-modules.md │ ├── files.md │ ├── globals.md │ ├── module-resolution.md │ ├── modules.md │ ├── namespaces.md │ ├── project.md │ └── tsconfig.md ├── promise.md ├── quick │ ├── browser.md │ └── nodejs.md ├── rest-parameters.md ├── spread-operator.md ├── staging │ ├── async-await.md │ └── generators.md ├── state │ └── mobx.md ├── styleguide │ ├── sample.js │ ├── sample.ts │ ├── styleguide.md │ └── tsconfig.json ├── template-strings.md ├── testing │ ├── cypress.md │ ├── intro.md │ └── jest.md ├── tips │ ├── barrel.md │ ├── build-toggles.md │ ├── classesAreUseful.md │ ├── create-arrays.md │ ├── currying.md │ ├── defaultIsBad.md │ ├── functionParameters.md │ ├── jquery.md │ ├── lazyObjectLiteralInitialization.md │ ├── main.md │ ├── nominalTyping.md │ ├── outFile.md │ ├── propertySetters.md │ ├── singleton.md │ ├── statefulFunctions.md │ ├── staticConstructor.md │ ├── stringEnums.md │ ├── typeInstantiation.md │ └── typed-event.md ├── tools │ ├── changelog.md │ ├── eslint.md │ ├── husky.md │ ├── intro.md │ └── prettier.md ├── types │ ├── @types.md │ ├── advanced.md │ ├── ambient │ │ ├── d.ts.md │ │ ├── intro.md │ │ └── variables.md │ ├── callable.md │ ├── discriminated-unions.md │ ├── exceptions.md │ ├── freshness.md │ ├── functions.md │ ├── generics.md │ ├── index-signatures.md │ ├── interfaces.md │ ├── lib.d.ts.md │ ├── literal-types.md │ ├── migrating.md │ ├── mixins.md │ ├── moving-types.md │ ├── never.md │ ├── readonly.md │ ├── type-assertion.md │ ├── type-compatibility.md │ ├── type-inference.md │ ├── type-system.md │ └── typeGuard.md └── why-typescript.md ├── footer.md ├── header.html ├── images ├── atomts.png ├── errors │ └── interpreting-errors │ │ └── ide.png ├── github.png ├── promise states and fates.png ├── promise states and fates.vsd ├── venn.png └── venn.vsd └── snippets └── md-snippets.cson /.gitattributes: -------------------------------------------------------------------------------- 1 | # core.autocrlf 2 | * text=auto 3 | 4 | *.js linguist-language=TypeScript 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac 2 | *.DS_Store 3 | 4 | # IDEs 5 | .alm 6 | .vscode 7 | 8 | 9 | # Node rules: 10 | ## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 11 | .grunt 12 | 13 | ## Dependency directory 14 | ## Commenting this out is preferred by some people, see 15 | ## https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git 16 | node_modules 17 | 18 | # Book build output 19 | _book 20 | 21 | # eBook build output 22 | *.epub 23 | *.mobi 24 | *.pdf 25 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | This book is developed using [GitBook](https://github.com/GitbookIO/gitbook). Authored in Markdown files (I use [atom](http://atom.io)). 4 | 5 | Here's how to setup a Dev Environment: 6 | 7 | ``` 8 | npm install gitbook-cli -g 9 | gitbook serve . 10 | ``` 11 | > Note: serve needs port `35729` (for live reload) and `4000` for serving http://localhost:4000. 12 | 13 | Also you can mostly just edit the `.md` files in [`/docs`](https://github.com/basarat/typescript-book/docs) using github and create a Pull Request (PR). 14 | 15 | # Code 16 | All the code for the book is in the `/code` folder. Tested with `atom-typescript`. 17 | 18 | ### More Gitbook Tips 19 | * Links best work if they are relative (e.g. `./foo.md`) to the *current* file. 20 | * For links in the same file (`#foo-bar` style links) best to click the heading on github to get what gitbook expects. 21 | 22 | ### TypeScript Compiler Docs 23 | Thanks to the TypeScript team for providing much of the docs: https://github.com/Microsoft/TypeScript/wiki/Architectural-Overview that are used to write the compiler story. 24 | -------------------------------------------------------------------------------- /GLOSSARY.md: -------------------------------------------------------------------------------- 1 | # Duck Typing 2 | If it walks like a duck and quacks like a duck, it is a duck. For TypeScript if it has all the members structurally then it is okay for other things (irrespecitive of name) that accept that structure. 3 | 4 | # OE 5 | Operating Environment. I'd like to use the term Operating System, but that is not necessarily what I mean here. Think Browser,Node.js,WScriptHost etc. 6 | 7 | # Incremental Parsing 8 | Re-Parsing as the user edits the code. -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Creative Commons 2 | 3 | https://creativecommons.org/licenses/by/4.0/ 4 | -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | { 2 | "language": "en", 3 | "author": "Basarat Ali Syed", 4 | "title": "TypeScript Deep Dive", 5 | "plugins": ["edit-link", "github", "adsense","header"], 6 | "pluginsConfig": { 7 | "layout": { 8 | "headerPath" : "header.html" 9 | }, 10 | "lunr": { 11 | "ignoreSpecialCharacters": true 12 | }, 13 | "edit-link": { 14 | "base": "https://github.com/basarat/typescript-book/tree/master", 15 | "label": "Edit This Page" 16 | }, 17 | "github": { 18 | "url": "https://github.com/basarat/typescript-book/" 19 | }, 20 | "adsense": { 21 | "client": "ca-pub-4656761253552116", 22 | "slot": "2017468453", 23 | "format": "auto", 24 | "element": ".page-inner section", 25 | "position": "bottom" 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /code/async-await/es5/asyncAwaitES5.ts: -------------------------------------------------------------------------------- 1 | function delay(milliseconds: number, count: number): Promise { 2 | return new Promise(resolve => { 3 | setTimeout(() => { 4 | resolve(count); 5 | }, milliseconds); 6 | }); 7 | } 8 | 9 | // Una función async siempre devuelve una Promesa 10 | async function dramaticWelcome(): Promise { 11 | console.log("Hello"); 12 | 13 | for (let i = 0; i < 5; i++) { 14 | // await is converting Promise into number 15 | const count:number = await delay(500, i); 16 | console.log(count); 17 | } 18 | 19 | console.log("World!"); 20 | } 21 | 22 | dramaticWelcome(); -------------------------------------------------------------------------------- /code/async-await/es5/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */ 4 | "module": "commonjs", /* Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'. */ 5 | "lib": ["dom", "es2015.promise", "es5"] /* Specify library files to be included in the compilation: */ 6 | }, 7 | "files": [ 8 | "./asyncAwaitES5.ts" 9 | ] 10 | } -------------------------------------------------------------------------------- /code/async-await/es6/asyncAwaitES6.js: -------------------------------------------------------------------------------- 1 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 2 | return new (P || (P = Promise))(function (resolve, reject) { 3 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 4 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 5 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } 6 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 7 | }); 8 | }; 9 | function delay(milliseconds, count) { 10 | return new Promise(resolve => { 11 | setTimeout(() => { 12 | resolve(count); 13 | }, milliseconds); 14 | }); 15 | } 16 | // Una función async siempre devuelve una Promesa 17 | function dramaticWelcome() { 18 | return __awaiter(this, void 0, void 0, function* () { 19 | console.log("Hello"); 20 | for (let i = 0; i < 5; i++) { 21 | // await is converting Promise into number 22 | const count = yield delay(500, i); 23 | console.log(count); 24 | } 25 | console.log("World!"); 26 | }); 27 | } 28 | dramaticWelcome(); 29 | -------------------------------------------------------------------------------- /code/async-await/es6/asyncAwaitES6.ts: -------------------------------------------------------------------------------- 1 | function delay(milliseconds: number, count: number): Promise { 2 | return new Promise(resolve => { 3 | setTimeout(() => { 4 | resolve(count); 5 | }, milliseconds); 6 | }); 7 | } 8 | 9 | // Una función async siempre devuelve una Promesa 10 | async function dramaticWelcome(): Promise { 11 | console.log("Hello"); 12 | 13 | for (let i = 0; i < 5; i++) { 14 | // await is converting Promise into number 15 | const count:number = await delay(500, i); 16 | console.log(count); 17 | } 18 | 19 | console.log("World!"); 20 | } 21 | 22 | dramaticWelcome(); -------------------------------------------------------------------------------- /code/async-await/es6/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */ 4 | "module": "commonjs" /* Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'. */ 5 | }, 6 | "files": [ 7 | "./asyncAwaitES6.ts" 8 | ] 9 | } -------------------------------------------------------------------------------- /code/compiler/node_modules/.bin/ntsc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | basedir=`dirname "$0"` 3 | 4 | case `uname` in 5 | *CYGWIN*) basedir=`cygpath -w "$basedir"`;; 6 | esac 7 | 8 | if [ -x "$basedir/node" ]; then 9 | "$basedir/node" "$basedir/../ntypescript/bin/tsc" "$@" 10 | ret=$? 11 | else 12 | node "$basedir/../ntypescript/bin/tsc" "$@" 13 | ret=$? 14 | fi 15 | exit $ret 16 | -------------------------------------------------------------------------------- /code/compiler/node_modules/.bin/ntsc.cmd: -------------------------------------------------------------------------------- 1 | @IF EXIST "%~dp0\node.exe" ( 2 | "%~dp0\node.exe" "%~dp0\..\ntypescript\bin\tsc" %* 3 | ) ELSE ( 4 | @SETLOCAL 5 | @SET PATHEXT=%PATHEXT:;.JS;=;% 6 | node "%~dp0\..\ntypescript\bin\tsc" %* 7 | ) -------------------------------------------------------------------------------- /code/compiler/node_modules/.bin/ntse: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | basedir=`dirname "$0"` 3 | 4 | case `uname` in 5 | *CYGWIN*) basedir=`cygpath -w "$basedir"`;; 6 | esac 7 | 8 | if [ -x "$basedir/node" ]; then 9 | "$basedir/node" "$basedir/../ntypescript/bin/tse" "$@" 10 | ret=$? 11 | else 12 | node "$basedir/../ntypescript/bin/tse" "$@" 13 | ret=$? 14 | fi 15 | exit $ret 16 | -------------------------------------------------------------------------------- /code/compiler/node_modules/.bin/ntse.cmd: -------------------------------------------------------------------------------- 1 | @IF EXIST "%~dp0\node.exe" ( 2 | "%~dp0\node.exe" "%~dp0\..\ntypescript\bin\tse" %* 3 | ) ELSE ( 4 | @SETLOCAL 5 | @SET PATHEXT=%PATHEXT:;.JS;=;% 6 | node "%~dp0\..\ntypescript\bin\tse" %* 7 | ) -------------------------------------------------------------------------------- /code/compiler/node_modules/.bin/ntsserver: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | basedir=`dirname "$0"` 3 | 4 | case `uname` in 5 | *CYGWIN*) basedir=`cygpath -w "$basedir"`;; 6 | esac 7 | 8 | if [ -x "$basedir/node" ]; then 9 | "$basedir/node" "$basedir/../ntypescript/bin/tsserver" "$@" 10 | ret=$? 11 | else 12 | node "$basedir/../ntypescript/bin/tsserver" "$@" 13 | ret=$? 14 | fi 15 | exit $ret 16 | -------------------------------------------------------------------------------- /code/compiler/node_modules/.bin/ntsserver.cmd: -------------------------------------------------------------------------------- 1 | @IF EXIST "%~dp0\node.exe" ( 2 | "%~dp0\node.exe" "%~dp0\..\ntypescript\bin\tsserver" %* 3 | ) ELSE ( 4 | @SETLOCAL 5 | @SET PATHEXT=%PATHEXT:;.JS;=;% 6 | node "%~dp0\..\ntypescript\bin\tsserver" %* 7 | ) -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/.npmignore: -------------------------------------------------------------------------------- 1 | TypeScript 2 | .gitmodules 3 | tests -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - iojs 4 | env: 5 | global: 6 | - secure: WXkeUKwWKTv2uUCyIiDdQ0e5gQCoX9gGj6wiNh9G7IATqcecxTw6cpQGj3J8YWDIjbtNXfAkJwohhGtXYr7VnkXRA1s0POYM+8cvM5I+ZDtZkXM9EvCwMYxf9XZ8qQ/4fegeSoZqfx1qgh+Sfh6Wp93I4W+AfB8VONLIGgXr172QGwYmkynPpC//mYA6sUZoQo4Y796PtBblc+7oM0a5A5chQ5r1CVqPqRZ/i9aNrH2UTdYjCMNE395LqwHSJGk5eunT5ebA4OcClme1wL78MJtGS1ZZIOEHSBv7mBrOcp29kYknc/m1PaOYBMdppmRBLr6Q5oUg8QzaILW2TypsWkosWpSlbemW1lsutqlFRkmtsjfX3ZVOoeIx/7J9v+pDA2gb7VMtNzwlkRpcLfHBmfuXuiPNXwLS1Ogl2D8JUD+rjwB3FI6pE2zZqNL7zMe7yhCQ/1wqGdlNqB1Ifb9T2RRkDCEUr+dw3sGn6Ecgk4XThUwY3vVzABj0C906Wc7UpsVvf1qjLCRg48lYG8kmhLqEylL+IUs3XXMSv69/YLxnDvRdF/d1FZHWKcoTeWYmXr3k1q0ePYEDXpX6/8MXWix1Qql4AAOjIxOgRufBPlDWe6QS2b97K4OPo+m3cf/RaLPz+jUOpf59l6CNnceBYLKs00Taf0KSgs+YVADAV6M= 7 | before_script: 8 | - git config --global user.email "basaratali@gmail.com" 9 | - git config --global user.name "Travis-CI" 10 | - git remote set-url origin https://github.com/basarat/ntypescript.git 11 | script: 12 | - bash prepare.sh 13 | after_success: 14 | - git config credential.helper "store --file=.git/credentials" 15 | - echo "https://${GH_TOKEN}:@github.com" > .git/credentials 16 | - git config --global push.default matching 17 | - bash release.sh 18 | 19 | # Only master kicks a build 20 | branches: 21 | only: 22 | - master 23 | 24 | deploy: 25 | provider: npm 26 | email: basaratali@gmail.com 27 | api_key: 28 | secure: qUecySLzb8peMNoWTuKuPM6YgHTwyLhs0mOyuWmeovJZzpxoLxG3qCfQjxekCSnGmLqd3nSKuP2T8DXaytJqEcB/c2eSrsv13jcw4hfAl1EAQjqFL18xzf7zO6mpjDZWP+eWdNwr1jH+Z+uvu1Qkb0uVvDtYgaWai31JpY4q7Vz+OKKz3V+loqeygysm5IZFEpzV96XI39EZZSwMa0pC51g1gZVx71AbORWI9zyPEw0QDysSr4NkU5DaqCvk0GVVGwU03YMFRJVQWs2H8B0SfQT1Nj8glUIYfXZ8BuZr7nTYwCnOSa27Yn5H17XHc+Zl8CPRtTNlkaVUSpDEF4hpMj2fKpePd4OXRzkud2aXMyd+IEmvf/s9kZRstFic7mly9vKS06jtQsWISeI1fULF121DKtoQX+zmwU2TFD21xo/VeuSHD2YpSkfbVnb9/ezqOAx/eqQXaTIOfw31+eR2eAb2bhgW0T6p7aJXMrIBw+VaPxa6Ckls6ItOKMBj/l00Hn/fP8oucNte9FlgevcS+ieOmzGw4Y2tb1RK5AUYQA+F39xXRH0upiYk8BxvLq9Qg/xuCUbMxJ8Ax37ObVW2QBdVhJlNleMt3iZMQQS/OLUHgGPyFmrXmavc3yQM38Bot6ScOsUehe/ViOIMeNO4mRCxUdgKEAyi0SgL604nFKE= 29 | on: 30 | repo: TypeStrong/ntypescript 31 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Release 2 | 3 | ## Quickly 4 | 5 | Quick workflow (runs `prepare` and `release`): 6 | 7 | ```sh 8 | quick.sh 9 | ``` 10 | 11 | ## Manually 12 | 13 | ```sh 14 | prepare.sh 15 | ``` 16 | 17 | Manual verification here ... then: 18 | 19 | ```sh 20 | release.sh 21 | npm publish 22 | ``` 23 | 24 | ## globals 25 | 26 | You can try the globals using: 27 | 28 | ``` 29 | npm link 30 | ``` 31 | 32 | # Inspiration 33 | https://github.com/Arnavion/typescript-github 34 | 35 | # Travis 36 | Cron job setup using : http://traviscron.pythonanywhere.com/ for daily 37 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | grunt.initConfig({ 4 | ntypescript: { 5 | options: { 6 | project: '.' 7 | }, 8 | default: {}, 9 | pass: { 10 | options: { 11 | project: './tests/grunt/pass' 12 | } 13 | }, 14 | fail: { 15 | options: { 16 | project: './tests/grunt/fail' 17 | } 18 | }, 19 | }, 20 | }); 21 | 22 | grunt.loadTasks('tasks'); 23 | // They would do: 24 | // grunt.loadNpmTasks('ntypescript'); 25 | 26 | grunt.registerTask('default', ['ntypescript:default']); 27 | }; -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/LICENCE: -------------------------------------------------------------------------------- 1 | MIT 2 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.{build} 2 | os: MinGW 3 | environment: 4 | access_token: 5 | secure: keMAbmi7iJ7xgQfIIv8IWFhu2h/ghgJc43OzQ2Fr554ZPQzhohZ9/+2TA3886VCo 6 | build_script: 7 | - prepare.sh 8 | on_success: 9 | - git config --global credential.helper store 10 | - ps: Add-Content "$env:USERPROFILE\.git-credentials" "https://$($env:access_token):x-oauth-basic@github.com`n" 11 | - release.sh 12 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/bin/tsc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('./tsc.js') 3 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/bin/tse: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('../tse.js') 3 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/bin/tsserver: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('./tsserver.js') 3 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/extensions/addExtensions.d.ts: -------------------------------------------------------------------------------- 1 | declare var require: any, __dirname: any; 2 | declare var fs: any; 3 | declare var EOL: string; 4 | declare function readFile(filePath: string): string; 5 | declare function writeFile(filePath: string, content: string): void; 6 | declare var dtsWithGlobal: string; 7 | declare var dtsExtensionsGlobal: string; 8 | declare var jsOriginal: string; 9 | declare var jsExtensions: string; 10 | declare var finalDtsLocation: string; 11 | declare var finalJsLocation: string; 12 | declare var finalDtsContent: string; 13 | declare var finalJsContent: string; 14 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/extensions/addExtensions.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var EOL = require('os').EOL; 3 | function readFile(filePath) { 4 | return fs.readFileSync(__dirname + '/' + filePath, 'utf8'); 5 | } 6 | function writeFile(filePath, content) { 7 | fs.writeFileSync(__dirname + '/' + filePath, content); 8 | } 9 | var dtsWithGlobal = readFile('../bin/typescriptServices.d.ts'); 10 | var dtsExtensionsGlobal = readFile('./extensions.d.ts'); 11 | var jsOriginal = readFile('../bin/typescript.js'); 12 | var jsExtensions = readFile('./extensions.js'); 13 | var finalDtsLocation = '../bin/ntypescript.d.ts'; 14 | var finalJsLocation = '../bin/ntypescript.js'; 15 | var finalDtsContent = dtsWithGlobal + EOL + dtsExtensionsGlobal + EOL + "\ndeclare module \"ntypescript\" {\n export = ts;\n}\n"; 16 | var finalJsContent = jsOriginal + EOL + jsExtensions; 17 | writeFile(finalDtsLocation, finalDtsContent); 18 | writeFile(finalJsLocation, finalJsContent); 19 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/extensions/addExtensions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This script is responsible for making required modifications to our version of TypeScript 3 | */ 4 | declare var require, __dirname; 5 | var fs = require('fs'); 6 | var EOL: string = require('os').EOL; 7 | function readFile(filePath: string): string { 8 | return fs.readFileSync(__dirname + '/' + filePath, 'utf8'); 9 | } 10 | function writeFile(filePath: string, content: string) { 11 | fs.writeFileSync(__dirname + '/' + filePath, content); 12 | } 13 | var dtsWithGlobal = readFile('../bin/typescriptServices.d.ts'); 14 | var dtsExtensionsGlobal = readFile('./extensions.d.ts'); 15 | 16 | var jsOriginal = readFile('../bin/typescript.js'); 17 | var jsExtensions = readFile('./extensions.js'); 18 | 19 | var finalDtsLocation = '../bin/ntypescript.d.ts'; 20 | var finalJsLocation = '../bin/ntypescript.js'; 21 | 22 | var finalDtsContent = dtsWithGlobal + EOL + dtsExtensionsGlobal + EOL + ` 23 | declare module "ntypescript" { 24 | export = ts; 25 | } 26 | `; 27 | var finalJsContent = jsOriginal + EOL + jsExtensions; 28 | 29 | writeFile(finalDtsLocation, finalDtsContent); 30 | writeFile(finalJsLocation, finalJsContent); 31 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/extensions/extensions.d.ts: -------------------------------------------------------------------------------- 1 | declare module ts { 2 | function syntaxKindToName(kind: ts.SyntaxKind): string; 3 | } 4 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/extensions/extensions.js: -------------------------------------------------------------------------------- 1 | var ts; 2 | (function (ts) { 3 | function syntaxKindToName(kind) { 4 | return ts.SyntaxKind[kind]; 5 | } 6 | ts.syntaxKindToName = syntaxKindToName; 7 | })(ts || (ts = {})); 8 | if (typeof global !== "undefined") { 9 | global.ts = ts; 10 | } 11 | if (typeof window !== "undefined") { 12 | window.ts = ts; 13 | } 14 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/extensions/extensions.ts: -------------------------------------------------------------------------------- 1 | module ts { 2 | export function syntaxKindToName(kind: ts.SyntaxKind): string { 3 | return (ts).SyntaxKind[kind]; 4 | } 5 | } 6 | if (typeof global !== "undefined") { 7 | (global as any).ts = ts; 8 | } 9 | if (typeof window !== "undefined") { 10 | (window as any).ts = ts; 11 | } 12 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/extensions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.5.0-beta", 3 | "compilerOptions": { 4 | "target": "es5", 5 | "module": "commonjs", 6 | "isolatedModules": false, 7 | "jsx": "react", 8 | "experimentalDecorators": true, 9 | "emitDecoratorMetadata": true, 10 | "declaration": true, 11 | "noImplicitAny": false, 12 | "removeComments": true, 13 | "noLib": false, 14 | "preserveConstEnums": true, 15 | "suppressImplicitAnyIndexErrors": true 16 | }, 17 | "filesGlob": [ 18 | "./**/*.ts", 19 | "./**/*.tsx", 20 | "!./node_modules/**/*", 21 | "../bin/typescriptServices.d.ts", 22 | "!./extensions.d.ts", 23 | "!./addExtensions.d.ts" 24 | ], 25 | "files": [ 26 | "./addExtensions.ts", 27 | "./extensions.ts", 28 | "../bin/typescriptServices.d.ts" 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/kicktravis: -------------------------------------------------------------------------------- 1 | 2015-07-14 [ci skip] Version: 1.201507141013.1+649e40b1711096de54eb325a702597d3ee62e9ef 2 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ntypescript", 3 | "version": "1.201507141013.1", 4 | "description": "Latest code from microsoft/typescript packaged and released", 5 | "main": "./bin/ntypescript.js", 6 | "bin": { 7 | "ntsc": "./bin/tsc", 8 | "ntsserver": "./bin/tsserver", 9 | "ntse": "./bin/tse" 10 | }, 11 | "typescript": { 12 | "definition": "./bin/ntypescript.d.ts" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/basarat/ntypescript.git" 17 | }, 18 | "keywords": [ 19 | "typescript", 20 | "gruntplugin" 21 | ], 22 | "author": { 23 | "name": "basaratali@gmail.com" 24 | }, 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/basarat/ntypescript/issues" 28 | }, 29 | "homepage": "https://github.com/basarat/ntypescript#readme", 30 | "devDependencies": { 31 | "grunt": "^0.4.5" 32 | }, 33 | "gitHead": "d14e0bfcc2679bd611f94358d838782477c61a07", 34 | "_id": "ntypescript@1.201507141013.1", 35 | "scripts": {}, 36 | "_shasum": "62c6d9cc066383a6e5709ae7c879948de060dcfc", 37 | "_from": "ntypescript@1.201507141013.1", 38 | "_npmVersion": "2.12.1", 39 | "_nodeVersion": "2.3.4", 40 | "_npmUser": { 41 | "name": "basarat", 42 | "email": "basaratali@gmail.com" 43 | }, 44 | "maintainers": [ 45 | { 46 | "name": "basarat", 47 | "email": "basaratali@gmail.com" 48 | } 49 | ], 50 | "dist": { 51 | "shasum": "62c6d9cc066383a6e5709ae7c879948de060dcfc", 52 | "tarball": "http://registry.npmjs.org/ntypescript/-/ntypescript-1.201507141013.1.tgz" 53 | }, 54 | "directories": {}, 55 | "_resolved": "https://registry.npmjs.org/ntypescript/-/ntypescript-1.201507141013.1.tgz", 56 | "readme": "ERROR: No README data found!" 57 | } 58 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/prepare.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | 5 | git submodule update --recursive --init 6 | 7 | # Official Microsoft/TypeScript clone 8 | typeScriptDirectory='./TypeScript' 9 | 10 | cd $typeScriptDirectory 11 | 12 | git clean -xfd 13 | git fetch origin 14 | git reset --hard origin/master 15 | 16 | # Fix jakefile to expose the internal APIs to service 17 | < Jakefile.js > Jakefile.new.js sed -E "s/\*stripInternal\*\/ true/\*stripInternal\*\/ false/" 18 | mv Jakefile.new.js Jakefile.js 19 | 20 | # Install jake 21 | npm install jake 22 | 23 | # Build once with LKG 24 | ./node_modules/.bin/jake release tsc --trace 25 | cp ./built/local/* ./bin/ 26 | 27 | # Rebuild with itself 28 | ./node_modules/.bin/jake release clean local --trace 29 | 30 | # Copy output 31 | cp ./built/local/* ./bin/tsc ./bin/tsserver ../bin/ 32 | 33 | # Reset sub typescript 34 | git reset --hard origin/master 35 | 36 | # add custom extension 37 | node ../extensions/addExtensions.js 38 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/quick.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | ./prepare.sh 6 | 7 | ./release.sh 8 | 9 | npm publish -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/register.js: -------------------------------------------------------------------------------- 1 | /// 2 | var t = require('./bin/typescript.js'); 3 | var fileExtension = ['.ts', '.tsx']; 4 | exports.isTypeScript = function (file) { return /\.(ts|tsx)$/.test(file); }; 5 | var fs = require('fs'); 6 | function loadFile(module, filename) { 7 | var js = t.transpile(fs.readFileSync(filename, 'utf8')); 8 | module._compile(js, filename); 9 | } 10 | exports.loadFile = loadFile; 11 | if (require.extensions) { 12 | for (var _i = 0; _i < fileExtension.length; _i++) { 13 | var ext = fileExtension[_i]; 14 | require.extensions[ext] = loadFile; 15 | } 16 | } 17 | var child_process = require('child_process'); 18 | if (child_process) { 19 | var fork = child_process.fork; 20 | var binary = require.resolve('./bin/tse'); 21 | child_process.fork = function (path, args, options) { 22 | if (exports.isTypeScript(path)) { 23 | if (!Array.isArray(args)) { 24 | options = args || {}; 25 | args = []; 26 | } 27 | args = [path].concat(args); 28 | path = binary; 29 | } 30 | fork(path, args, options); 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/register.ts: -------------------------------------------------------------------------------- 1 | /// 2 | var t: typeof ts = require('./bin/typescript.js'); 3 | 4 | /** Determine if a filename represents a TypeScript file. */ 5 | var fileExtension = ['.ts', '.tsx']; 6 | export var isTypeScript = (file) => /\.(ts|tsx)$/.test(file); 7 | 8 | /** Load and runt TypeScript for Node */ 9 | import fs = require('fs'); 10 | export function loadFile(module, filename) { 11 | var js = t.transpile(fs.readFileSync(filename,'utf8')); 12 | module._compile(js, filename); 13 | } 14 | 15 | /** If the installed version of Node supports require.extensions, register TypeScript as an extension. */ 16 | if (require.extensions) { 17 | for (var ext of fileExtension) { 18 | require.extensions[ext] = loadFile; 19 | } 20 | } 21 | 22 | /** If we’re on Node, patch child_process.fork so that TypeScript is able to fork both TypeScript files, and JavaScript files, directly. */ 23 | import child_process = require('child_process'); 24 | if (child_process) { 25 | var {fork} = child_process; 26 | var binary = require.resolve('./bin/tse'); 27 | child_process.fork = function(path, args?, options?) { 28 | if (isTypeScript(path)) { 29 | if (!Array.isArray(args)) { 30 | options = args || {} 31 | args = [] 32 | } 33 | args = [path].concat(args) 34 | path = binary 35 | } 36 | fork(path, args, options) 37 | } 38 | } -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | # Get the git commit hash 5 | typeScriptDirectory='./TypeScript' 6 | cd $typeScriptDirectory 7 | commitHash=`git rev-parse HEAD` 8 | cd .. 9 | 10 | # Version of this script 11 | toolsVersion="1" 12 | 13 | commitVersion="1.$(date +%Y%m%d%H%M).$toolsVersion+$commitHash" 14 | commitName="$(date +%Y-%m-%d) [ci skip] Version: $commitVersion" 15 | 16 | # Kick travis 17 | echo $commitName > kicktravis 18 | 19 | # Update package.json 20 | < package.json > package.json.new sed -E "s/(\s+\"version\": \")[^\"]+(\",)/\1$commitVersion\2/" 21 | mv package.json.new package.json 22 | echo "Adding to git" 23 | git add -A 24 | git checkout master 25 | git status 26 | 27 | # Commit,tag,push,publish 28 | echo "Committing" 29 | git commit -m "$commitName" 30 | git merge HEAD@{1} 31 | echo "Pushing commit" 32 | git push 33 | 34 | echo "Tagging" 35 | git tag $commitVersion 36 | echo "Pushing tags" 37 | git push --tags 38 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/tasks/ntypescript.js: -------------------------------------------------------------------------------- 1 | /* 2 | * ntypescript 3 | * https://github.com/basarat/ntypescript 4 | * 5 | * Copyright (c) 2015 Basarat Syed 6 | * Licensed under the MIT license. 7 | */ 8 | var path = require("path"); 9 | function gruntPlugin(grunt) { 10 | grunt.registerMultiTask('ntypescript', 'TypeScript grunt plugin', function () { 11 | var options = { 12 | project: '.', 13 | }; 14 | options = this.options(options); 15 | if (!options.project) { 16 | console.error('tsconfig must be specified using options'); 17 | return false; 18 | } 19 | var project = path.resolve(options.project); 20 | var args = [__dirname + '/../bin/tsc', '-p', project]; 21 | var done = this.async(); 22 | grunt.util.spawn({ 23 | cmd: process.execPath, 24 | args: args 25 | }, function (error, result, code) { 26 | console.log(result.stdout || result.stderr); 27 | done(!code); 28 | }); 29 | }); 30 | } 31 | ; 32 | module.exports = gruntPlugin; 33 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/tasks/ntypescript.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ntypescript 3 | * https://github.com/basarat/ntypescript 4 | * 5 | * Copyright (c) 2015 Basarat Syed 6 | * Licensed under the MIT license. 7 | */ 8 | 9 | import * as path from "path"; 10 | 11 | function gruntPlugin(grunt) { 12 | grunt.registerMultiTask('ntypescript', 'TypeScript grunt plugin', function() { 13 | // Merge task-specific and/or target-specific options with these defaults. 14 | var options = { 15 | project: '.', 16 | }; 17 | options = this.options(options); 18 | 19 | if (!options.project) { 20 | console.error('tsconfig must be specified using options'); 21 | return false; 22 | } 23 | 24 | const project: string = path.resolve(options.project); 25 | const args = [__dirname + '/../bin/tsc', '-p', project]; 26 | // console.log(args); // Debug 27 | 28 | var done = this.async(); 29 | grunt.util.spawn({ 30 | cmd: process.execPath, 31 | args: args 32 | }, (error, result, code: number) => { 33 | console.log(result.stdout || result.stderr); 34 | done(!code); 35 | }); 36 | }); 37 | }; 38 | 39 | export = gruntPlugin; -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.5.0-alpha", 3 | "compilerOptions": { 4 | "target": "es5", 5 | "module": "commonjs", 6 | "jsx": "react", 7 | "declaration": false, 8 | "noImplicitAny": false, 9 | "removeComments": true, 10 | "noLib": false, 11 | "preserveConstEnums": true, 12 | "suppressImplicitAnyIndexErrors": true 13 | }, 14 | "filesGlob": [ 15 | "./**/*.ts", 16 | "./**/*.tsx", 17 | "!./bin/**/*", 18 | "!./TypeScript/**/*", 19 | "!./node_modules/**/*", 20 | "!./tests/grunt/**/*.ts" 21 | ], 22 | "files": [ 23 | "./extensions/addExtensions.d.ts", 24 | "./extensions/addExtensions.ts", 25 | "./extensions/extensions.d.ts", 26 | "./extensions/extensions.ts", 27 | "./register.ts", 28 | "./tasks/ntypescript.ts", 29 | "./tests/tse/1start.ts", 30 | "./tests/tse/2iwillfork.ts", 31 | "./tests/tse/3iwilllogargs.ts", 32 | "./tse.ts", 33 | "./typings/gruntjs/gruntjs.d.ts", 34 | "./typings/node/node.d.ts", 35 | "./typings/tsd.d.ts" 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/tsd.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "v4", 3 | "repo": "borisyankov/DefinitelyTyped", 4 | "ref": "master", 5 | "path": "typings", 6 | "bundle": "typings/tsd.d.ts", 7 | "installed": { 8 | "node/node.d.ts": { 9 | "commit": "c7b1128cc9a8f5797bade826e7632b36b06a856c" 10 | }, 11 | "gruntjs/gruntjs.d.ts": { 12 | "commit": "c7b1128cc9a8f5797bade826e7632b36b06a856c" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/tse.js: -------------------------------------------------------------------------------- 1 | /// 2 | var t = require('./bin/typescript.js'); 3 | var node = process.argv[0]; 4 | var script = process.argv[2]; 5 | process.argv = [node].concat(process.argv.slice(2)); 6 | if (!script) { 7 | process.exit(0); 8 | } 9 | var fs = require('fs'); 10 | var jsContent = t.transpile(fs.readFileSync(script, 'utf8')); 11 | var dir = fs.realpathSync('.'); 12 | var mainModule = require.main; 13 | mainModule.paths = require('module')._nodeModulePaths(dir); 14 | mainModule._compile(jsContent, mainModule.filename); 15 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/tse.ts: -------------------------------------------------------------------------------- 1 | // This transpiles the file and then executes it 2 | /// 3 | var t: typeof ts = require('./bin/typescript.js'); 4 | var node = process.argv[0]; 5 | var script = process.argv[2]; 6 | // Remove `tse` from the argv 7 | process.argv = [node].concat(process.argv.slice(2)); 8 | 9 | if (!script) { 10 | process.exit(0); 11 | } 12 | 13 | // Register globally: 14 | import register = require("./register"); 15 | 16 | 17 | import vm = require('vm'); 18 | import fs = require('fs'); 19 | import path = require('path'); 20 | var jsContent = t.transpile(fs.readFileSync(script, 'utf8')); 21 | 22 | // https://github.com/jashkenas/coffeescript/blob/master/lib/coffee-script/command.js#L114 23 | // `compilePath` triggered because of `opts.run` 24 | // Then : https://github.com/jashkenas/coffeescript/blob/342b395b0a7c135dfea1fe5f66fa536794d114fe/src/coffee-script.coffee#L109 25 | 26 | // Assign paths for node_modules loading 27 | var dir = fs.realpathSync('.'); 28 | var mainModule = require.main; 29 | mainModule.paths = require('module')._nodeModulePaths(dir); 30 | mainModule._compile(jsContent, mainModule.filename); 31 | 32 | 33 | -------------------------------------------------------------------------------- /code/compiler/node_modules/ntypescript/typings/tsd.d.ts: -------------------------------------------------------------------------------- 1 | 2 | /// 3 | /// 4 | -------------------------------------------------------------------------------- /code/compiler/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "compiler", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "runScanner.js", 6 | "dependencies": { 7 | "ntypescript": "1.201507141013.1" 8 | }, 9 | "devDependencies": {}, 10 | "scripts": { 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "author": "", 14 | "license": "ISC" 15 | } 16 | -------------------------------------------------------------------------------- /code/compiler/parser/runParser.js: -------------------------------------------------------------------------------- 1 | var ts = require("ntypescript"); 2 | function printAllChildren(node, depth) { 3 | if (depth === void 0) { depth = 0; } 4 | console.log(new Array(depth + 1).join('----'), ts.syntaxKindToName(node.kind), node.pos, node.end); 5 | depth++; 6 | node.getChildren().forEach(function (c) { return printAllChildren(c, depth); }); 7 | } 8 | var sourceCode = "\nvar foo = 123;\n".trim(); 9 | var sourceFile = ts.createSourceFile('foo.ts', sourceCode, 1, true); 10 | printAllChildren(sourceFile); 11 | -------------------------------------------------------------------------------- /code/compiler/parser/runParser.ts: -------------------------------------------------------------------------------- 1 | import * as ts from "ntypescript"; 2 | 3 | function printAllChildren(node: ts.Node, depth = 0) { 4 | console.log(new Array(depth + 1).join('----'), ts.syntaxKindToName(node.kind), node.pos, node.end); 5 | depth++; 6 | node.getChildren().forEach(c=> printAllChildren(c, depth)); 7 | } 8 | 9 | var sourceCode = ` 10 | var foo = 123; 11 | `.trim(); 12 | 13 | var sourceFile = ts.createSourceFile('foo.ts', sourceCode, ts.ScriptTarget.ES5, true); 14 | printAllChildren(sourceFile); -------------------------------------------------------------------------------- /code/compiler/scanner/runScanner.js: -------------------------------------------------------------------------------- 1 | var ts = require("ntypescript"); 2 | var scanner = ts.createScanner(2, true); 3 | function initializeState(text) { 4 | scanner.setText(text); 5 | scanner.setOnError(function (message, length) { 6 | console.error(message); 7 | }); 8 | scanner.setScriptTarget(1); 9 | scanner.setLanguageVariant(0); 10 | } 11 | initializeState("\nvar foo = 123;\n".trim()); 12 | var token = scanner.scan(); 13 | while (token != 1) { 14 | console.log(ts.syntaxKindToName(token)); 15 | token = scanner.scan(); 16 | } 17 | -------------------------------------------------------------------------------- /code/compiler/scanner/runScanner.ts: -------------------------------------------------------------------------------- 1 | import * as ts from "ntypescript"; 2 | 3 | // TypeScript has a singelton scanner 4 | const scanner = ts.createScanner(ts.ScriptTarget.Latest, /*skipTrivia*/ true); 5 | 6 | // That is initialized using a function `initializeState` similar to 7 | function initializeState(text: string) { 8 | scanner.setText(text); 9 | scanner.setOnError((message: ts.DiagnosticMessage, length: number) => { 10 | console.error(message); 11 | }); 12 | scanner.setScriptTarget(ts.ScriptTarget.ES5); 13 | scanner.setLanguageVariant(ts.LanguageVariant.Standard); 14 | } 15 | 16 | // Sample usage 17 | initializeState(` 18 | var foo = 123; 19 | `.trim()); 20 | 21 | // Start the scanning 22 | var token = scanner.scan(); 23 | while (token != ts.SyntaxKind.EndOfFileToken) { 24 | console.log(ts.syntaxKindToName(token)); 25 | token = scanner.scan(); 26 | } 27 | -------------------------------------------------------------------------------- /code/compiler/scanner/runScannerWithPositions.js: -------------------------------------------------------------------------------- 1 | var ts = require("ntypescript"); 2 | var scanner = ts.createScanner(2, true); 3 | function initializeState(text) { 4 | scanner.setText(text); 5 | scanner.setOnError(function (message, length) { 6 | console.error(message); 7 | }); 8 | scanner.setScriptTarget(1); 9 | scanner.setLanguageVariant(0); 10 | } 11 | initializeState("\nvar foo = 123;\n".trim()); 12 | var token = scanner.scan(); 13 | while (token != 1) { 14 | var currentToken = ts.syntaxKindToName(token); 15 | var tokenStart = scanner.getStartPos(); 16 | token = scanner.scan(); 17 | var tokenEnd = scanner.getStartPos(); 18 | console.log(currentToken, tokenStart, tokenEnd); 19 | } 20 | -------------------------------------------------------------------------------- /code/compiler/scanner/runScannerWithPositions.ts: -------------------------------------------------------------------------------- 1 | import * as ts from "ntypescript"; 2 | 3 | // TypeScript has a singelton scanner 4 | const scanner = ts.createScanner(ts.ScriptTarget.Latest, /*skipTrivia*/ true); 5 | 6 | // That is initialized using a function `initializeState` similar to 7 | function initializeState(text: string) { 8 | scanner.setText(text); 9 | scanner.setOnError((message: ts.DiagnosticMessage, length: number) => { 10 | console.error(message); 11 | }); 12 | scanner.setScriptTarget(ts.ScriptTarget.ES5); 13 | scanner.setLanguageVariant(ts.LanguageVariant.Standard); 14 | } 15 | 16 | // Sample usage 17 | initializeState(` 18 | var foo = 123; 19 | `.trim()); 20 | 21 | // Start the scanning 22 | var token = scanner.scan(); 23 | while (token != ts.SyntaxKind.EndOfFileToken) { 24 | let currentToken = ts.syntaxKindToName(token); 25 | let tokenStart = scanner.getStartPos(); 26 | token = scanner.scan(); 27 | let tokenEnd = scanner.getStartPos(); 28 | console.log(currentToken, tokenStart, tokenEnd); 29 | } 30 | -------------------------------------------------------------------------------- /code/compiler/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.5.0-beta", 3 | "compilerOptions": { 4 | "target": "es5", 5 | "module": "commonjs", 6 | "isolatedModules": false, 7 | "jsx": "react", 8 | "experimentalDecorators": true, 9 | "emitDecoratorMetadata": true, 10 | "declaration": false, 11 | "noImplicitAny": false, 12 | "removeComments": true, 13 | "noLib": false, 14 | "preserveConstEnums": true, 15 | "suppressImplicitAnyIndexErrors": true 16 | }, 17 | "filesGlob": [ 18 | "./**/*.ts", 19 | "./**/*.tsx", 20 | "!./node_modules/**/*" 21 | ], 22 | "files": [ 23 | "./parser/runParser.ts", 24 | "./scanner/runScanner.ts", 25 | "./scanner/runScannerWithPositions.ts", 26 | "./typings/node/node.d.ts", 27 | "./typings/tsd.d.ts" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /code/compiler/tsd.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "v4", 3 | "repo": "borisyankov/DefinitelyTyped", 4 | "ref": "master", 5 | "path": "typings", 6 | "bundle": "typings/tsd.d.ts", 7 | "installed": { 8 | "node/node.d.ts": { 9 | "commit": "38c6ccfde0e67ff10d7408e0ee8b7720b3f21d3b" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /code/compiler/typings/tsd.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /code/declarationspaces/declarationspace.js: -------------------------------------------------------------------------------- 1 | var first; 2 | (function (first) { 3 | var Foo = (function () { 4 | function Foo() { 5 | } 6 | return Foo; 7 | })(); 8 | var foo; 9 | var bar; 10 | var bas; 11 | })(first = exports.first || (exports.first = {})); 12 | var second; 13 | (function (second) { 14 | ; 15 | var bar = Bar; 16 | })(second || (second = {})); 17 | var third; 18 | (function (third) { 19 | var Foo = (function () { 20 | function Foo() { 21 | } 22 | return Foo; 23 | })(); 24 | var someVar = Foo; 25 | var someOtherVar = 123; 26 | })(third || (third = {})); 27 | var fourn; 28 | (function (fourn) { 29 | var foo = 123; 30 | var bar; 31 | })(fourn || (fourn = {})); 32 | var meh; 33 | (function (meh) { 34 | var something = {}; 35 | })(meh || (meh = {})); 36 | var utility; 37 | (function (utility) { 38 | function log(msg) { 39 | console.log(msg); 40 | } 41 | utility.log = log; 42 | function error(msg) { 43 | console.error(msg); 44 | } 45 | utility.error = error; 46 | })(utility || (utility = {})); 47 | utility.log('Call me'); 48 | utility.error('maybe!'); 49 | var importing; 50 | (function (importing) { 51 | var Foo = (function () { 52 | function Foo() { 53 | } 54 | return Foo; 55 | })(); 56 | var Bar = Foo; 57 | var bar; 58 | })(importing || (importing = {})); 59 | var importing; 60 | (function (importing) { 61 | var Foo = (function () { 62 | function Foo() { 63 | } 64 | return Foo; 65 | })(); 66 | importing.Foo = Foo; 67 | })(importing || (importing = {})); 68 | var Bar = importing.Foo; 69 | var bar; 70 | var typeofAnnotation; 71 | (function (typeofAnnotation) { 72 | var foo = 123; 73 | var bar; 74 | bar = 456; 75 | bar = '789'; 76 | })(typeofAnnotation || (typeofAnnotation = {})); 77 | -------------------------------------------------------------------------------- /code/declarationspaces/declarationspace.ts: -------------------------------------------------------------------------------- 1 | export module first { 2 | class Foo { } 3 | interface Bar { } 4 | type Bas = {} 5 | 6 | var foo: Foo; 7 | var bar: Bar; 8 | var bas: Bas; 9 | } 10 | 11 | namespace second { 12 | interface Bar { }; 13 | var bar = Bar; // ERROR: "cannot find name 'Bar'" 14 | } 15 | 16 | namespace third { 17 | class Foo { } 18 | var someVar = Foo; 19 | var someOtherVar = 123; 20 | } 21 | 22 | namespace fourn { 23 | var foo = 123; 24 | var bar: foo; // ERROR: "cannot find name 'foo'" 25 | } 26 | 27 | 28 | namespace meh { 29 | var something = {}; 30 | // (function(something) { 31 | // something.foo = 123; 32 | // })(something || something = {}) 33 | } 34 | 35 | namespace utility { 36 | export function log(msg) { 37 | console.log(msg); 38 | } 39 | export function error(msg) { 40 | console.error(msg); 41 | } 42 | } 43 | 44 | // usage 45 | utility.log('Call me'); 46 | utility.error('maybe!'); 47 | 48 | 49 | module importing { 50 | class Foo { } 51 | var Bar = Foo; 52 | var bar: Bar; // ERROR: "cannot find name 'Bar'" 53 | } 54 | 55 | namespace importing { 56 | export class Foo { } 57 | } 58 | 59 | import Bar = importing.Foo; 60 | var bar: Bar; // Okay 61 | 62 | namespace typeofAnnotation { 63 | var foo = 123; 64 | var bar: typeof foo; // `bar` has the same type as `foo` (here `number`) 65 | bar = 456; // Okay 66 | bar = '789'; // ERROR: Type `string` is not `assignable` to type `number` 67 | } -------------------------------------------------------------------------------- /code/dynamic-import-expressions/dynamicImportExpression.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | function myApp() { 3 | import(/* webpackChunkName: "momentjs" */ "moment") 4 | .then(function (moment) { 5 | // lazyModule tiene todos los tipos correctos, la autocompletar funciona, 6 | // el chequeo de tipos funciona y las referencias de código también \o/ 7 | var time = moment().format(); 8 | console.log("TypeScript >= 2.4.0 Dynamic Import Expression:"); 9 | console.log(time); 10 | }) 11 | .catch(function (err) { 12 | console.log("Failed to load moment", err); 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /code/dynamic-import-expressions/dynamicImportExpression.ts: -------------------------------------------------------------------------------- 1 | 2 | function myApp() { 3 | import(/* webpackChunkName: "momentjs" */ "moment") 4 | .then((moment) => { 5 | // lazyModule tiene todos los tipos correctos, la autocompletar funciona, 6 | // el chequeo de tipos funciona y las referencias de código también \o/ 7 | const time = moment().format(); 8 | console.log("TypeScript >= 2.4.0 Dynamic Import Expression:"); 9 | console.log(time); 10 | }) 11 | .catch((err) => { 12 | console.log("Failed to load moment", err); 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /code/dynamic-import-expressions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dynamic-import-expressions", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "dynamicImportExpression.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Jose Quinto Zamora - https://blog.josequinto.com", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "typescript": "^2.4.1" 13 | }, 14 | "dependencies": { 15 | "moment": "^2.18.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /code/dynamic-import-expressions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "esnext", 5 | "lib": [ 6 | "dom", 7 | "es5", 8 | "scripthost", 9 | "es2015.promise" 10 | ], 11 | "strict": true, 12 | "moduleResolution": "node" 13 | }, 14 | "files": [ 15 | "./dynamicImportExpression.ts" 16 | ] 17 | } -------------------------------------------------------------------------------- /code/errors/common-errors.ts: -------------------------------------------------------------------------------- 1 | ga(); 2 | 3 | import {debounce} from "underscore"; 4 | -------------------------------------------------------------------------------- /code/errors/interpreting-errors.ts: -------------------------------------------------------------------------------- 1 | export const module = 123; 2 | 3 | type SomethingComplex = { 4 | foo: number, 5 | bar: string 6 | } 7 | function takeSomethingComplex(arg: SomethingComplex) { 8 | } 9 | function getBar(): string { 10 | return 'some bar'; 11 | } 12 | 13 | ////////////////////////////////// 14 | // Example error production 15 | ////////////////////////////////// 16 | const fail = { 17 | foo: 123, 18 | bar: getBar 19 | }; 20 | 21 | takeSomethingComplex(fail); // TS ERROR HAPPENS HERE 22 | -------------------------------------------------------------------------------- /code/errors/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noEmit": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /code/es6/classes/abstract.js: -------------------------------------------------------------------------------- 1 | exports.foo = 123; 2 | var Restable = (function () { 3 | function Restable() { 4 | this.abstract = toJSON(); 5 | } 6 | return Restable; 7 | })(); 8 | -------------------------------------------------------------------------------- /code/es6/classes/abstract.ts: -------------------------------------------------------------------------------- 1 | export var foo = 123; 2 | 3 | class Restable { 4 | abstract toJSON() : any; 5 | } 6 | 7 | -------------------------------------------------------------------------------- /code/es6/classes/class.js: -------------------------------------------------------------------------------- 1 | var __extends = this.__extends || function (d, b) { 2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 3 | function __() { this.constructor = d; } 4 | __.prototype = b.prototype; 5 | d.prototype = new __(); 6 | }; 7 | var Point = (function () { 8 | function Point(x, y) { 9 | this.x = x; 10 | this.y = y; 11 | } 12 | Point.prototype.add = function (point) { 13 | return new Point(this.x + point.x, this.y + point.y); 14 | }; 15 | return Point; 16 | })(); 17 | var p1 = new Point(0, 10); 18 | var p2 = new Point(10, 20); 19 | var p3 = p1.add(p2); 20 | var Point3D = (function (_super) { 21 | __extends(Point3D, _super); 22 | function Point3D(x, y, z) { 23 | _super.call(this, x, y); 24 | this.z = z; 25 | } 26 | Point3D.prototype.add = function (point) { 27 | var point2D = _super.prototype.add.call(this, point); 28 | return new Point3D(point2D.x, point2D.y, this.z + point.z); 29 | }; 30 | return Point3D; 31 | })(Point); 32 | var Something = (function () { 33 | function Something() { 34 | Something.instances++; 35 | } 36 | Something.instances = 0; 37 | return Something; 38 | })(); 39 | var s1 = new Something(); 40 | var s2 = new Something(); 41 | console.log(Something.instances); 42 | -------------------------------------------------------------------------------- /code/es6/classes/class.ts: -------------------------------------------------------------------------------- 1 | class Point { 2 | x: number; 3 | y: number; 4 | constructor(x: number, y: number) { 5 | this.x = x; 6 | this.y = y; 7 | } 8 | add(point: Point) { 9 | return new Point(this.x + point.x, this.y + point.y); 10 | } 11 | } 12 | 13 | var p1 = new Point(0, 10); 14 | var p2 = new Point(10, 20); 15 | var p3 = p1.add(p2); // {x:10,y:30} 16 | 17 | class Point3D extends Point { 18 | z: number; 19 | constructor(x: number, y: number, z: number) { 20 | super(x, y); 21 | this.z = z; 22 | } 23 | add(point: Point3D) { 24 | var point2D = super.add(point); 25 | return new Point3D(point2D.x, point2D.y, this.z + point.z); 26 | } 27 | } 28 | 29 | class Something { 30 | static instances = 0; 31 | constructor() { 32 | Something.instances++; 33 | } 34 | } 35 | 36 | var s1 = new Something(); 37 | var s2 = new Something(); 38 | console.log(Something.instances); // 2 39 | -------------------------------------------------------------------------------- /code/es6/classes/super.js: -------------------------------------------------------------------------------- 1 | var __extends = (this && this.__extends) || function (d, b) { 2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 3 | function __() { this.constructor = d; } 4 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 5 | }; 6 | exports.foo = 123; 7 | var asdf; 8 | (function (asdf) { 9 | var Base = (function () { 10 | function Base() { 11 | } 12 | Base.prototype.log = function () { console.log('hello world'); }; 13 | return Base; 14 | })(); 15 | var Child = (function (_super) { 16 | __extends(Child, _super); 17 | function Child() { 18 | _super.apply(this, arguments); 19 | } 20 | Child.prototype.logWorld = function () { _super.prototype.log.call(this); }; 21 | ; 22 | return Child; 23 | })(Base); 24 | })(asdf || (asdf = {})); 25 | var bse; 26 | (function (bse) { 27 | var Base = (function () { 28 | function Base() { 29 | this.log = function () { console.log('hello world'); }; 30 | } 31 | return Base; 32 | })(); 33 | var Child = (function (_super) { 34 | __extends(Child, _super); 35 | function Child() { 36 | _super.apply(this, arguments); 37 | } 38 | Child.prototype.logWorld = function () { this.log(); }; 39 | ; 40 | return Child; 41 | })(Base); 42 | })(bse || (bse = {})); 43 | var quz; 44 | (function (quz) { 45 | var Base = (function () { 46 | function Base() { 47 | this.log = function () { console.log('hello world'); }; 48 | } 49 | return Base; 50 | })(); 51 | var Child = (function (_super) { 52 | __extends(Child, _super); 53 | function Child() { 54 | _super.apply(this, arguments); 55 | } 56 | Child.prototype.logWorld = function () { _super.prototype.log.call(this); }; 57 | ; 58 | return Child; 59 | })(Base); 60 | })(quz || (quz = {})); 61 | -------------------------------------------------------------------------------- /code/es6/classes/super.ts: -------------------------------------------------------------------------------- 1 | export var foo = 123; 2 | 3 | module asdf { 4 | class Base { 5 | log() { console.log('hello world'); } 6 | } 7 | 8 | class Child extends Base { 9 | logWorld() { super.log() }; 10 | } 11 | } 12 | 13 | module bse { 14 | class Base { 15 | log = () => { console.log('hello world'); } 16 | } 17 | 18 | class Child extends Base { 19 | logWorld() { this.log() }; 20 | } 21 | } 22 | 23 | module quz { 24 | class Base { 25 | log = () => { console.log('hello world'); } 26 | } 27 | 28 | class Child extends Base { 29 | logWorld() { super.log() }; // ERROR : only `public` and `protected` methods of base class are accessible via `super` 30 | } 31 | } -------------------------------------------------------------------------------- /code/es6/classes/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.4.1", 3 | "compilerOptions": { 4 | "target": "es5", 5 | "module": "commonjs", 6 | "declaration": false, 7 | "noImplicitAny": false, 8 | "removeComments": true, 9 | "noLib": false 10 | }, 11 | "filesGlob": [ 12 | "./**/*.ts", 13 | "!./node_modules/**/*.ts" 14 | ], 15 | "files": [ 16 | "./abstract.ts", 17 | "./class.ts", 18 | "./super.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /code/es6/const.js: -------------------------------------------------------------------------------- 1 | exports.asdfasdfasfadf = 123; 2 | var mustbeinit; 3 | (function (mustbeinit) { 4 | var foo; 5 | })(mustbeinit || (mustbeinit = {})); 6 | var cantbechanged; 7 | (function (cantbechanged) { 8 | var foo = 123; 9 | foo = 456; 10 | })(cantbechanged || (cantbechanged = {})); 11 | var block; 12 | (function (block) { 13 | var foo = 123; 14 | if (true) { 15 | var foo_1 = 456; 16 | } 17 | })(block || (block = {})); 18 | var protectvariablereference; 19 | (function (protectvariablereference) { 20 | var foo = { bar: 123 }; 21 | foo = { bar: 456 }; 22 | })(protectvariablereference || (protectvariablereference = {})); 23 | var noProtectDeep; 24 | (function (noProtectDeep) { 25 | var foo = { bar: 123 }; 26 | foo.bar = 456; 27 | })(noProtectDeep || (noProtectDeep = {})); 28 | -------------------------------------------------------------------------------- /code/es6/const.ts: -------------------------------------------------------------------------------- 1 | export var asdfasdfasfadf = 123; 2 | 3 | 4 | namespace mustbeinit { 5 | const foo; 6 | } 7 | 8 | namespace cantbechanged { 9 | const foo = 123; 10 | foo = 456; 11 | } 12 | 13 | 14 | namespace block { 15 | const foo = 123; 16 | if (true) { 17 | const foo = 456; // Allowed as its a new variable limited to this `if` block 18 | } 19 | } 20 | 21 | 22 | namespace protectvariablereference { 23 | const foo = { bar: 123 }; 24 | foo = { bar: 456 }; // ERROR : Left hand side of an assignment expression cannot be a constant 25 | } 26 | 27 | 28 | namespace noProtectDeep { 29 | const foo = { bar: 123 }; 30 | foo.bar = 456; // Allowed! 31 | } 32 | -------------------------------------------------------------------------------- /code/es6/destructuring.js: -------------------------------------------------------------------------------- 1 | exports.destructuring = true; 2 | var m1; 3 | (function (m1) { 4 | var x = 1, y = 2; 5 | _a = [ 6 | y, 7 | x 8 | ], x = _a[0], y = _a[1]; 9 | console.log(x, y); 10 | var _a; 11 | })(m1 || (m1 = {})); 12 | var m2; 13 | (function (m2) { 14 | var rect = { 15 | x: 0, 16 | y: 10, 17 | width: 15, 18 | height: 20 19 | }; 20 | var x = rect.x, y = rect.y, width = rect.width, height = rect.height; 21 | console.log(x, y, width, height); 22 | })(m2 || (m2 = {})); 23 | var m3; 24 | (function (m3) { 25 | var _a = [ 26 | 1, 27 | 2, 28 | 3, 29 | 4 30 | ], x = _a[0], y = _a[1], remaining = _a.slice(2); 31 | console.log(x, y, remaining); 32 | })(m3 || (m3 = {})); 33 | var m3; 34 | (function (m3) { 35 | var _a = [ 36 | 1, 37 | 2, 38 | 3, 39 | 4 40 | ], x = _a[0], remaining = _a.slice(2); 41 | console.log(x, remaining); 42 | })(m3 || (m3 = {})); 43 | -------------------------------------------------------------------------------- /code/es6/destructuring.ts: -------------------------------------------------------------------------------- 1 | export var destructuring = true; 2 | 3 | 4 | module m1 { 5 | var x = 1, y = 2; 6 | [x, y] = [y, x]; 7 | console.log(x, y); // 1,2 8 | } 9 | 10 | module m2 { 11 | var rect = { x: 0, y: 10, width: 15, height: 20 }; 12 | var {x, y, width, height} = rect; 13 | console.log(x, y, width, height); // 0,10,15,20 14 | } 15 | 16 | module m3 { 17 | var [x, y, ...remaining] = [1, 2, 3, 4]; 18 | console.log(x, y, remaining); // 1, 2, [3,4] 19 | } 20 | 21 | module m3 { 22 | var [x, , ...remaining] = [1, 2, 3, 4]; 23 | console.log(x, remaining); // 1, [3,4] 24 | } 25 | -------------------------------------------------------------------------------- /code/es6/enums.ts: -------------------------------------------------------------------------------- 1 | export var foo = 123; 2 | 3 | enum Color { 4 | Red, 5 | Green, 6 | Blue 7 | } 8 | 9 | enum Color { 10 | DarkRed = 3, 11 | DarkGreen, 12 | DarkBlue 13 | } 14 | 15 | var col = Color.Red; 16 | col = 0; // Effectively same as Color.Red 17 | 18 | 19 | enum Tristate { 20 | False, 21 | True, 22 | Unknown 23 | } 24 | 25 | var lie = Tristate.False; 26 | 27 | /*enum AnimalFlags { 28 | None = 0, 29 | HasClaws = 1 << 0, 30 | CanFly = 1 << 1, 31 | EatsFish = 1 << 2, 32 | Endangered = 1 << 3 33 | }*/ 34 | 35 | enum AnimalFlags { 36 | None = 0, 37 | HasClaws = 1 << 0, 38 | CanFly = 1 << 1, 39 | } 40 | 41 | function printAnimalAbilities(animal) { 42 | var animalFlags = animal.flags; 43 | if (animalFlags & AnimalFlags.HasClaws) { 44 | console.log('animal has claws'); 45 | } 46 | if (animalFlags & AnimalFlags.CanFly) { 47 | console.log('animal can fly'); 48 | } 49 | if (animalFlags == AnimalFlags.None){ 50 | console.log('nothing'); 51 | } 52 | } 53 | 54 | var animal = { flags: AnimalFlags.None }; 55 | printAnimalAbilities(animal); // nothing 56 | animal.flags |= AnimalFlags.HasClaws; 57 | printAnimalAbilities(animal); // animal has claws 58 | animal.flags &= ~AnimalFlags.HasClaws; 59 | printAnimalAbilities(animal); // nothing 60 | animal.flags |= AnimalFlags.HasClaws | AnimalFlags.CanFly; 61 | printAnimalAbilities(animal); // animal has claws, animal can fly 62 | 63 | 64 | namespace EnumsWithStatics { 65 | enum Weekday { 66 | Monday, 67 | Tuesday, 68 | Wednesday, 69 | Thursday, 70 | Friday, 71 | Saturday, 72 | Sunday 73 | } 74 | namespace Weekday { 75 | export function isBusinessDay(day: Weekday) { 76 | switch (day) { 77 | case Weekday.Saturday: 78 | case Weekday.Sunday: 79 | return false; 80 | default: 81 | return true; 82 | } 83 | } 84 | } 85 | 86 | const mon = Weekday.Monday; 87 | const sun = Weekday.Sunday; 88 | console.log(Weekday.isBusinessDay(mon)); // true 89 | console.log(Weekday.isBusinessDay(sun)); // false 90 | } 91 | -------------------------------------------------------------------------------- /code/es6/for..of.js: -------------------------------------------------------------------------------- 1 | exports.forof = true; 2 | var m0; 3 | (function (m0) { 4 | var someArray = [ 5 | 9, 6 | 2, 7 | 5 8 | ]; 9 | for (var item in someArray) { 10 | console.log(item); 11 | } 12 | })(m0 || (m0 = {})); 13 | var m1; 14 | (function (m1) { 15 | var someArray = [ 16 | 9, 17 | 2, 18 | 5 19 | ]; 20 | for (var _i = 0; _i < someArray.length; _i++) { 21 | var item = someArray[_i]; 22 | console.log(item); 23 | } 24 | })(m1 || (m1 = {})); 25 | var m2; 26 | (function (m2) { 27 | var hello = "is it me you're looking for?"; 28 | for (var _i = 0; _i < hello.length; _i++) { 29 | var char = hello[_i]; 30 | console.log(char); 31 | } 32 | })(m2 || (m2 = {})); 33 | var m2; 34 | (function (m2) { 35 | var articleParagraphs = document.querySelectorAll("article > p"); 36 | for (var _i = 0; _i < articleParagraphs.length; _i++) { 37 | var paragraph = articleParagraphs[_i]; 38 | paragraph.classList.add("read"); 39 | } 40 | })(m2 || (m2 = {})); 41 | -------------------------------------------------------------------------------- /code/es6/for..of.ts: -------------------------------------------------------------------------------- 1 | export var forof = true; 2 | 3 | module m0 { 4 | var someArray = [9, 2, 5]; 5 | for (var item in someArray) { 6 | console.log(item); 7 | } 8 | } 9 | 10 | module m1 { 11 | var someArray = [9, 2, 5]; 12 | for (var item of someArray) { 13 | console.log(item); 14 | } 15 | } 16 | 17 | module m2 { 18 | var hello = "is it me you're looking for?"; 19 | for (var char of hello) { 20 | console.log(char); // is it me you're looking for? 21 | } 22 | } 23 | 24 | module m2 { 25 | let articleParagraphs = document.querySelectorAll("article > p"); 26 | // Error: Nodelist is not an array type or a string type 27 | for (let paragraph of articleParagraphs) { 28 | paragraph.classList.add("read"); 29 | } 30 | } -------------------------------------------------------------------------------- /code/es6/forof.js: -------------------------------------------------------------------------------- 1 | exports.forof = true; 2 | var m0; 3 | (function (m0) { 4 | var someArray = [ 5 | 9, 6 | 2, 7 | 5 8 | ]; 9 | for (var item in someArray) { 10 | console.log(item); 11 | } 12 | })(m0 || (m0 = {})); 13 | var m1; 14 | (function (m1) { 15 | var someArray = [ 16 | 9, 17 | 2, 18 | 5 19 | ]; 20 | for (var _i = 0; _i < someArray.length; _i++) { 21 | var item = someArray[_i]; 22 | console.log(item); 23 | } 24 | })(m1 || (m1 = {})); 25 | var m2; 26 | (function (m2) { 27 | var hello = "is it me you're looking for?"; 28 | for (var _i = 0; _i < hello.length; _i++) { 29 | var char = hello[_i]; 30 | console.log(char); 31 | } 32 | })(m2 || (m2 = {})); 33 | var m2; 34 | (function (m2) { 35 | var articleParagraphs = document.querySelectorAll("article > p"); 36 | for (var _i = 0; _i < articleParagraphs.length; _i++) { 37 | var paragraph = articleParagraphs[_i]; 38 | paragraph.classList.add("read"); 39 | } 40 | })(m2 || (m2 = {})); 41 | -------------------------------------------------------------------------------- /code/es6/iterators.js: -------------------------------------------------------------------------------- 1 | var Component = (function () { 2 | function Component(name) { 3 | this.name = name; 4 | } 5 | return Component; 6 | }()); 7 | var Frame = (function () { 8 | function Frame(name, components) { 9 | this.name = name; 10 | this.components = components; 11 | this.pointer = 0; 12 | } 13 | Frame.prototype.next = function () { 14 | if (this.pointer < this.components.length) { 15 | return { 16 | done: false, 17 | value: this.components[this.pointer++] 18 | }; 19 | } 20 | else 21 | return { 22 | done: true 23 | }; 24 | }; 25 | return Frame; 26 | }()); 27 | var frame = new Frame("Door", [new Component("top"), new Component("bottom"), new Component("left"), new Component("right")]); 28 | var iteratorResult1 = frame.next(); 29 | var iteratorResult2 = frame.next(); 30 | var iteratorResult3 = frame.next(); 31 | var iteratorResult4 = frame.next(); 32 | var iteratorResult5 = frame.next(); 33 | var component = iteratorResult1.value; 34 | -------------------------------------------------------------------------------- /code/es6/iterators.ts: -------------------------------------------------------------------------------- 1 | // The book's chapter describes usage of Iterators with ES6 target 2 | // This example showing usage of iterators with ES5 target 3 | // 4 | // The example from the chapter should work in moderen browsers and Node 5 | // with target ES5 if you add es6.d.ts to the project 6 | 7 | class Component { 8 | constructor (public name: string) {} 9 | } 10 | 11 | class Frame { 12 | 13 | private pointer = 0; 14 | 15 | constructor(public name: string, public components: Component[]) {} 16 | 17 | public next(): {done: boolean, value?: Component} { 18 | if (this.pointer < this.components.length) { 19 | return { 20 | done: false, 21 | value: this.components[this.pointer++] 22 | } 23 | } else return { 24 | done: true 25 | } 26 | } 27 | 28 | } 29 | 30 | let frame = new Frame("Door", [new Component("top"), new Component("bottom"), new Component("left"), new Component("right")]); 31 | let iteratorResult1 = frame.next(); //{ done: false, value: Component { name: 'top' } } 32 | let iteratorResult2 = frame.next(); //{ done: false, value: Component { name: 'bottom' } } 33 | let iteratorResult3 = frame.next(); //{ done: false, value: Component { name: 'left' } } 34 | let iteratorResult4 = frame.next(); //{ done: false, value: Component { name: 'right' } } 35 | let iteratorResult5 = frame.next(); //{ done: true } 36 | 37 | //It is possible to access the value of iterator result via the value property: 38 | let component = iteratorResult1.value; //Component { name: 'top' } 39 | -------------------------------------------------------------------------------- /code/es6/let.js: -------------------------------------------------------------------------------- 1 | exports.asdfasdfasfadf = 123; 2 | var first; 3 | (function (first) { 4 | var something = [ 5 | 1, 6 | 2, 7 | 3 8 | ]; 9 | })(first || (first = {})); 10 | var second; 11 | (function (second) { 12 | var foo = 123; 13 | if (true) { 14 | var foo = 456; 15 | } 16 | console.log(foo); 17 | })(second || (second = {})); 18 | var third; 19 | (function (third) { 20 | var foo = 123; 21 | function test() { 22 | var foo = 456; 23 | } 24 | test(); 25 | console.log(foo); 26 | })(third || (third = {})); 27 | var fourth; 28 | (function (fourth) { 29 | var index = 0; 30 | var array = [ 31 | 1, 32 | 2, 33 | 3 34 | ]; 35 | for (var _index = 0; _index < array.length; _index++) { 36 | console.log(array[_index]); 37 | } 38 | console.log(index); 39 | })(fourth || (fourth = {})); 40 | var fifth; 41 | (function (fifth) { 42 | if (true) { 43 | var foo = 123; 44 | } 45 | })(fifth || (fifth = {})); 46 | var fifth; 47 | (function (fifth) { 48 | var foo = '123'; 49 | if (true) { 50 | var _foo = 123; 51 | } 52 | })(fifth || (fifth = {})); 53 | var closures; 54 | (function (closures) { 55 | var funcs = []; 56 | for (var i = 0; i < 3; i++) { 57 | funcs.push(function () { 58 | console.log(i); 59 | }); 60 | } 61 | for (var j = 0; j < 3; j++) { 62 | funcs[j](); 63 | } 64 | })(closures || (closures = {})); 65 | var closures2; 66 | (function (closures2) { 67 | var funcs = []; 68 | for (var i = 0; i < 3; i++) { 69 | (function () { 70 | var local = i; 71 | funcs.push(function () { 72 | console.log(local); 73 | }); 74 | })(); 75 | } 76 | for (var j = 0; j < 3; j++) { 77 | funcs[j](); 78 | } 79 | })(closures2 || (closures2 = {})); 80 | var closures3; 81 | (function (closures3) { 82 | var funcs = []; 83 | for (var i = 0; i < 3; i++) { 84 | funcs.push(function () { 85 | console.log(i); 86 | }); 87 | } 88 | for (var j = 0; j < 3; j++) { 89 | funcs[j](); 90 | } 91 | })(closures3 || (closures3 = {})); 92 | -------------------------------------------------------------------------------- /code/es6/let.ts: -------------------------------------------------------------------------------- 1 | export var asdfasdfasfadf = 123; 2 | 3 | module first { 4 | let something = [1, 2, 3]; 5 | 6 | 7 | } 8 | 9 | module second { 10 | var foo = 123; 11 | if (true) { 12 | var foo = 456; 13 | } 14 | console.log(foo); // 456 15 | } 16 | 17 | module third { 18 | var foo = 123; 19 | function test() { 20 | var foo = 456; 21 | } 22 | test(); 23 | console.log(foo); // 123 24 | } 25 | 26 | module fourth { 27 | var index = 0; 28 | var array = [1, 2, 3]; 29 | for (let index = 0; index < array.length; index++) { 30 | console.log(array[index]); 31 | } 32 | console.log(index); // 0 33 | } 34 | 35 | module fifth { 36 | if (true) { 37 | let foo = 123; 38 | } 39 | } 40 | 41 | module fifth { 42 | var foo = '123'; 43 | if (true) { 44 | let foo = 123; 45 | } 46 | } 47 | 48 | module closures { 49 | var funcs = []; 50 | // create a bunch of functions 51 | for (var i = 0; i < 3; i++) { 52 | funcs.push(function() { 53 | console.log(i); 54 | }) 55 | } 56 | // call them 57 | for (var j = 0; j < 3; j++) { 58 | funcs[j](); 59 | } 60 | } 61 | 62 | module closures2 { 63 | var funcs = []; 64 | // create a bunch of functions 65 | for (var i = 0; i < 3; i++) { 66 | (function() { 67 | var local = i; 68 | funcs.push(function() { 69 | console.log(local); 70 | }) 71 | })(); 72 | } 73 | // call them 74 | for (var j = 0; j < 3; j++) { 75 | funcs[j](); 76 | } 77 | } 78 | 79 | module closures3 { 80 | var funcs = []; 81 | // create a bunch of functions 82 | for (let i = 0; i < 3; i++) { // Error : loop contains 83 | funcs.push(function() { 84 | console.log(i); 85 | }) 86 | } 87 | // call them 88 | for (var j = 0; j < 3; j++) { 89 | funcs[j](); 90 | } 91 | } -------------------------------------------------------------------------------- /code/es6/rest-parameters.js: -------------------------------------------------------------------------------- 1 | var rest; 2 | (function (rest) { 3 | function iTakeItAll(first, second) { 4 | var allOthers = []; 5 | for (var _i = 2; _i < arguments.length; _i++) { 6 | allOthers[_i - 2] = arguments[_i]; 7 | } 8 | console.log(allOthers); 9 | } 10 | iTakeItAll('foo', 'bar'); 11 | iTakeItAll('foo', 'bar', 'bas', 'qux'); 12 | })(rest = exports.rest || (exports.rest = {})); 13 | -------------------------------------------------------------------------------- /code/es6/rest-parameters.ts: -------------------------------------------------------------------------------- 1 | export module rest { 2 | function iTakeItAll(first, second, ...allOthers) { 3 | console.log(allOthers); 4 | } 5 | iTakeItAll('foo', 'bar'); // [] 6 | iTakeItAll('foo', 'bar', 'bas', 'qux'); // ['bas','qux'] 7 | } -------------------------------------------------------------------------------- /code/es6/spread-operator.js: -------------------------------------------------------------------------------- 1 | var spread; 2 | (function (spread) { 3 | var list = [ 4 | 1, 5 | 2 6 | ]; 7 | list = list.concat([3, 4]); 8 | })(spread = exports.spread || (exports.spread = {})); 9 | -------------------------------------------------------------------------------- /code/es6/spread-operator.ts: -------------------------------------------------------------------------------- 1 | export module spread { 2 | var list = [1, 2]; 3 | list = [...list, 3, 4]; 4 | } -------------------------------------------------------------------------------- /code/es6/template-strings.js: -------------------------------------------------------------------------------- 1 | exports.templateStrings = '123'; 2 | var m1; 3 | (function (m1) { 4 | var lyrics = "Never gonna give you up \ 5 | \nNever gonna let you down"; 6 | console.log(lyrics); 7 | })(m1 || (m1 = {})); 8 | var m2; 9 | (function (m2) { 10 | var lyrics = "Never gonna give you up\nNever gonna let you down"; 11 | console.log(lyrics); 12 | })(m2 || (m2 = {})); 13 | var m3; 14 | (function (m3) { 15 | var lyrics = 'Never gonna give you up'; 16 | var html = '
' + lyrics + '
'; 17 | })(m3 || (m3 = {})); 18 | var m4; 19 | (function (m4) { 20 | var lyrics = 'Never gonna give you up'; 21 | var html = "
" + lyrics + "
"; 22 | })(m4 || (m4 = {})); 23 | var m5; 24 | (function (m5) { 25 | console.log("1 and 1 one make " + (1 + 1)); 26 | })(m5 || (m5 = {})); 27 | var m6; 28 | (function (m6) { 29 | var say = "a bird in hand > two in the bush"; 30 | var html = (_a = ["
I would just like to say : ", "
"], _a.raw = ["
I would just like to say : ", "
"], htmlEscape(_a, say)); 31 | function htmlEscape(literals) { 32 | var placeholders = []; 33 | for (var _i = 1; _i < arguments.length; _i++) { 34 | placeholders[_i - 1] = arguments[_i]; 35 | } 36 | var result = ""; 37 | for (var i = 0; i < placeholders.length; i++) { 38 | result += literals[i]; 39 | result += placeholders[i].replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(//g, '>'); 40 | } 41 | result += literals[literals.length - 1]; 42 | return result; 43 | } 44 | console.log(html); 45 | var _a; 46 | })(m6 || (m6 = {})); 47 | -------------------------------------------------------------------------------- /code/es6/template-strings.ts: -------------------------------------------------------------------------------- 1 | export var templateStrings = '123'; 2 | 3 | module m1 { 4 | var lyrics = "Never gonna give you up \ 5 | \nNever gonna let you down"; 6 | console.log(lyrics); 7 | } 8 | 9 | module m2 { 10 | var lyrics = `Never gonna give you up 11 | Never gonna let you down`; 12 | console.log(lyrics); 13 | } 14 | 15 | module m3 { 16 | var lyrics = 'Never gonna give you up'; 17 | var html = '
' + lyrics + '
'; 18 | } 19 | 20 | module m4 { 21 | var lyrics = 'Never gonna give you up'; 22 | var html = `
${lyrics}
`; 23 | } 24 | 25 | module m5 { 26 | console.log(`1 and 1 one make ${1 + 1}`); 27 | } 28 | 29 | module m6 { 30 | var say = "a bird in hand > two in the bush"; 31 | var html = htmlEscape `
I would just like to say : ${say}
` 32 | 33 | // a sample tag function 34 | function htmlEscape(literals, ...placeholders) { 35 | let result = ""; 36 | 37 | // Interleave the literals with the placeholders 38 | for (let i = 0; i < placeholders.length; i++) { 39 | result += literals[i]; 40 | result += placeholders[i] 41 | .replace(/&/g, '&') 42 | .replace(/"/g, '"') 43 | .replace(/'/g, ''') 44 | .replace(//g, '>'); 46 | } 47 | 48 | // add the last literal 49 | result += literals[literals.length - 1]; 50 | return result; 51 | } 52 | console.log(html); 53 | } -------------------------------------------------------------------------------- /code/es6/test.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melissarofman/typescript-book/aa9ca251cb7b4616183c0e2045a48a581d1d83c0/code/es6/test.js -------------------------------------------------------------------------------- /code/es6/test.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melissarofman/typescript-book/aa9ca251cb7b4616183c0e2045a48a581d1d83c0/code/es6/test.ts -------------------------------------------------------------------------------- /code/es6/tsconfig.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /code/javascript/closure.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | function outerFunction(arg) { 3 | var variableInOuterFunction = arg; 4 | function bar() { 5 | console.log(variableInOuterFunction); 6 | } 7 | bar(); 8 | } 9 | outerFunction("hello closure"); 10 | var another; 11 | (function (another) { 12 | function outerFunction(arg) { 13 | var variableInOuterFunction = arg; 14 | return function () { 15 | console.log(variableInOuterFunction); 16 | }; 17 | } 18 | var innerFunction = outerFunction("hello closure!"); 19 | innerFunction(); 20 | })(another = exports.another || (exports.another = {})); 21 | var revealing; 22 | (function (revealing) { 23 | function createCounter() { 24 | var val = 0; 25 | return { 26 | increment: function () { val++; }, 27 | getVal: function () { return val; } 28 | }; 29 | } 30 | var counter = createCounter(); 31 | counter.increment(); 32 | console.log(counter.getVal()); 33 | })(revealing = exports.revealing || (exports.revealing = {})); 34 | var server; 35 | (function (server) { 36 | server.on(function handler(req, res) { 37 | loadData(req.id).then(function (data) { 38 | res.send(data); 39 | }); 40 | }); 41 | })(server = exports.server || (exports.server = {})); 42 | -------------------------------------------------------------------------------- /code/javascript/closure.ts: -------------------------------------------------------------------------------- 1 | function outerFunction(arg) { 2 | var variableInOuterFunction = arg; 3 | 4 | function bar() { 5 | console.log(variableInOuterFunction); // Access a variable from the outer scope 6 | } 7 | 8 | // Call the local function to demonstrate that it has access to arg 9 | bar(); 10 | } 11 | 12 | outerFunction("hello closure"); // logs hello closure! 13 | 14 | 15 | export namespace another { 16 | function outerFunction(arg) { 17 | var variableInOuterFunction = arg; 18 | return function() { 19 | console.log(variableInOuterFunction); 20 | } 21 | } 22 | 23 | var innerFunction = outerFunction("hello closure!"); 24 | 25 | // Note the outerFunction has returned 26 | innerFunction(); // logs hello closure! 27 | } 28 | 29 | 30 | export namespace revealing { 31 | function createCounter() { 32 | let val = 0; 33 | return { 34 | increment() { val++ }, 35 | getVal() { return val } 36 | } 37 | } 38 | 39 | let counter = createCounter(); 40 | counter.increment(); 41 | console.log(counter.getVal()); // 1 42 | } 43 | 44 | export namespace server { 45 | server.on(function handler(req, res) { 46 | loadData(req.id).then(function(data) { 47 | // the `res` has been closed over and is available 48 | res.send(data); 49 | }) 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /code/javascript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "isolatedModules": false, 7 | "jsx": "react", 8 | "experimentalDecorators": true, 9 | "emitDecoratorMetadata": true, 10 | "declaration": false, 11 | "noImplicitAny": false, 12 | "noImplicitUseStrict": false, 13 | "removeComments": true, 14 | "noLib": false, 15 | "preserveConstEnums": true, 16 | "suppressImplicitAnyIndexErrors": true 17 | }, 18 | "exclude": [ 19 | "node_modules", 20 | "typings/browser", 21 | "typings/browser.d.ts" 22 | ], 23 | "compileOnSave": true, 24 | "buildOnSave": false, 25 | "atom": { 26 | "rewriteTsconfig": false 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /code/tips/bindIsBad.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var Adder = (function () { 3 | function Adder(a) { 4 | this.a = a; 5 | } 6 | Adder.prototype.add = function (b) { 7 | return this.a + b; 8 | }; 9 | return Adder; 10 | })(); 11 | function useAdd(add) { 12 | return add(456); 13 | } 14 | var adder = new Adder('mary had a little 🐑'); 15 | useAdd(adder.add.bind(adder)); 16 | useAdd(function (x) { return adder.add(x); }); 17 | function twoParams(a, b) { 18 | return a + b; 19 | } 20 | var curryOne = twoParams.bind(null, 123); 21 | curryOne(456); 22 | curryOne('456'); 23 | var betterCurry; 24 | (function (betterCurry) { 25 | function twoParams(a, b) { 26 | return a + b; 27 | } 28 | var curryOne = function (x) { return twoParams(123, x); }; 29 | curryOne(456); 30 | curryOne('456'); 31 | })(betterCurry || (betterCurry = {})); 32 | -------------------------------------------------------------------------------- /code/tips/bindIsBad.ts: -------------------------------------------------------------------------------- 1 | export var _asdfasdfsadf; 2 | 3 | class Adder { 4 | constructor(public a: string) { } 5 | 6 | add(b: string): string { 7 | return this.a + b; 8 | } 9 | } 10 | 11 | function useAdd(add: (x: number) => number) { 12 | return add(456); 13 | } 14 | 15 | let adder = new Adder('mary had a little 🐑'); 16 | useAdd(adder.add.bind(adder)); // No compile error! 17 | useAdd((x) => adder.add(x)); // Error: number is not assignable to string 18 | 19 | 20 | function twoParams(a: number, b: number) { 21 | return a + b; 22 | } 23 | let curryOne = twoParams.bind(null, 123); 24 | curryOne(456); // Okay but is not type checked! 25 | curryOne('456'); // Allowed because it wasn't type checked 26 | 27 | namespace betterCurry { 28 | function twoParams(a: number, b: number) { 29 | return a + b; 30 | } 31 | let curryOne = (x: number) => twoParams(123, x); 32 | curryOne(456); // Okay and type checked! 33 | curryOne('456'); // Error! 34 | } 35 | -------------------------------------------------------------------------------- /code/tips/currying.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var add = function (x) { return function (y) { return x + y; }; }; 3 | add(123)(456); 4 | var add123 = add(123); 5 | add123(456); 6 | -------------------------------------------------------------------------------- /code/tips/currying.ts: -------------------------------------------------------------------------------- 1 | export var _asdfasdfasdf; 2 | 3 | 4 | // A function that supports currying 5 | let add = (x: number) => (y: number) => x + y; 6 | 7 | // Simple usage 8 | add(123)(456); 9 | 10 | // curried 11 | let add123 = add(123); 12 | 13 | // use the curried function 14 | add123(456); 15 | -------------------------------------------------------------------------------- /code/tips/lazyObjectLiteralInitialization.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var JS; 3 | (function (JS) { 4 | var foo = {}; 5 | foo.bar = 123; 6 | foo.bas = "Hello World"; 7 | })(JS = exports.JS || (exports.JS = {})); 8 | var TS; 9 | (function (TS) { 10 | var foo = { 11 | bar: 123, 12 | bas: "Hello World", 13 | }; 14 | })(TS = exports.TS || (exports.TS = {})); 15 | var TSQuick; 16 | (function (TSQuick) { 17 | var foo = {}; 18 | foo.bar = 123; 19 | foo.bas = "Hello World"; 20 | })(TSQuick = exports.TSQuick || (exports.TSQuick = {})); 21 | var TSMiddle; 22 | (function (TSMiddle) { 23 | var foo = {}; 24 | foo.bar = 123; 25 | foo.bas = "Hello World"; 26 | foo.bar = 'Hello Stranger'; 27 | })(TSMiddle = exports.TSMiddle || (exports.TSMiddle = {})); 28 | -------------------------------------------------------------------------------- /code/tips/lazyObjectLiteralInitialization.ts: -------------------------------------------------------------------------------- 1 | export namespace JS { 2 | let foo = {}; 3 | foo.bar = 123; 4 | foo.bas = "Hello World"; 5 | } 6 | 7 | export namespace TS { 8 | let foo = { 9 | bar: 123, 10 | bas: "Hello World", 11 | }; 12 | } 13 | 14 | export namespace TSQuick { 15 | let foo = {} as any; 16 | foo.bar = 123; 17 | foo.bas = "Hello World"; 18 | } 19 | 20 | export namespace TSMiddle { 21 | interface Foo { 22 | bar: number 23 | bas: string 24 | } 25 | 26 | let foo = {} as Foo; 27 | foo.bar = 123; 28 | foo.bas = "Hello World"; 29 | 30 | // later in the codebase: 31 | foo.bar = 'Hello Stranger'; // Error: You probably misspelled `bas` as `bar`, cannot assign string to number 32 | } 33 | -------------------------------------------------------------------------------- /code/tips/mixins.js: -------------------------------------------------------------------------------- 1 | var __extends = (this && this.__extends) || function (d, b) { 2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 3 | function __() { this.constructor = d; } 4 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 5 | }; 6 | var Disposable = (function () { 7 | function Disposable() { 8 | } 9 | Disposable.prototype.dispose = function () { 10 | this.isDisposed = true; 11 | }; 12 | return Disposable; 13 | })(); 14 | var Activatable = (function () { 15 | function Activatable() { 16 | } 17 | Activatable.prototype.activate = function () { 18 | this.isActive = true; 19 | }; 20 | Activatable.prototype.deactivate = function () { 21 | this.isActive = false; 22 | }; 23 | return Activatable; 24 | })(); 25 | var ActivatibleDisposible = (function () { 26 | Disposable.apply(this); 27 | ActivatibleDisposible.apply(this); 28 | return this; 29 | }); 30 | var SmartObject = (function (_super) { 31 | __extends(SmartObject, _super); 32 | function SmartObject() { 33 | var _this = this; 34 | _super.call(this); 35 | setInterval(function () { return console.log(_this.isActive + " : " + _this.isDisposed); }, 500); 36 | } 37 | SmartObject.prototype.interact = function () { 38 | this.activate(); 39 | }; 40 | return SmartObject; 41 | })(ActivatibleDisposible); 42 | applyMixins(SmartObject, [Disposable, Activatable]); 43 | var smartObj = new SmartObject(); 44 | setTimeout(function () { return smartObj.interact(); }, 1000); 45 | function applyMixins(derivedCtor, baseCtors) { 46 | baseCtors.forEach(function (baseCtor) { 47 | Object.getOwnPropertyNames(baseCtor.prototype).forEach(function (name) { 48 | derivedCtor.prototype[name] = baseCtor.prototype[name]; 49 | }); 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /code/tips/mixins.ts: -------------------------------------------------------------------------------- 1 | // Disposable Mixin 2 | class Disposable { 3 | isDisposed: boolean; 4 | dispose() { 5 | this.isDisposed = true; 6 | } 7 | 8 | } 9 | 10 | // Activatable Mixin 11 | class Activatable { 12 | isActive: boolean; 13 | activate() { 14 | this.isActive = true; 15 | } 16 | deactivate() { 17 | this.isActive = false; 18 | } 19 | } 20 | 21 | interface ActivatibleDisposible extends Disposable, Activatable { 22 | new (): ActivatibleDisposible; 23 | } 24 | 25 | var ActivatibleDisposible:ActivatibleDisposible = (function(){ 26 | Disposable.apply(this); 27 | ActivatibleDisposible.apply(this); 28 | return this; 29 | }) 30 | 31 | class SmartObject extends ActivatibleDisposible { 32 | constructor() { 33 | super(); 34 | setInterval(() => console.log(this.isActive + " : " + this.isDisposed), 500); 35 | } 36 | 37 | interact() { 38 | this.activate(); 39 | } 40 | } 41 | applyMixins(SmartObject, [Disposable, Activatable]) 42 | 43 | var smartObj = new SmartObject(); 44 | setTimeout(() => smartObj.interact(), 1000); 45 | 46 | //////////////////////////////////////// 47 | // In your runtime library somewhere 48 | //////////////////////////////////////// 49 | 50 | function applyMixins(derivedCtor: any, baseCtors: any[]) { 51 | baseCtors.forEach(baseCtor => { 52 | Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => { 53 | derivedCtor.prototype[name] = baseCtor.prototype[name]; 54 | }) 55 | }); 56 | } -------------------------------------------------------------------------------- /code/tips/nominalTyping.js: -------------------------------------------------------------------------------- 1 | var EnumDriven; 2 | (function (EnumDriven) { 3 | var FooIdBrand; 4 | (function (FooIdBrand) { 5 | })(FooIdBrand || (FooIdBrand = {})); 6 | var BarIdBrand; 7 | (function (BarIdBrand) { 8 | })(BarIdBrand || (BarIdBrand = {})); 9 | var fooId; 10 | var barId; 11 | fooId = barId; 12 | barId = fooId; 13 | fooId = 'foo'; 14 | barId = 'bar'; 15 | var str; 16 | str = fooId; 17 | str = barId; 18 | })(EnumDriven || (EnumDriven = {})); 19 | var Interface; 20 | (function (Interface) { 21 | var fooId; 22 | var barId; 23 | fooId = barId; 24 | barId = fooId; 25 | fooId = barId; 26 | barId = fooId; 27 | fooId = 'foo'; 28 | barId = 'bar'; 29 | var str; 30 | str = fooId; 31 | str = barId; 32 | })(Interface || (Interface = {})); 33 | -------------------------------------------------------------------------------- /code/tips/nominalTyping.ts: -------------------------------------------------------------------------------- 1 | namespace Literal { 2 | /** Generic Id type */ 3 | type Id = { 4 | type: T, 5 | value: string, 6 | } 7 | 8 | /** Specific Id types */ 9 | type FooId = Id<'foo'>; 10 | type BarId = Id<'bar'>; 11 | 12 | /** Optional: contructors functions */ 13 | const createFoo = (value: string): FooId => ({ type: 'foo', value }); 14 | const createBar = (value: string): BarId => ({ type: 'bar', value }); 15 | 16 | let foo = createFoo('sample') 17 | let bar = createBar('sample'); 18 | 19 | foo = bar; // Error 20 | foo = foo; // Okay 21 | } 22 | 23 | namespace EnumDriven { 24 | // FOO 25 | enum FooIdBrand { } 26 | type FooId = FooIdBrand & string; 27 | 28 | // BAR 29 | enum BarIdBrand { } 30 | type BarId = BarIdBrand & string; 31 | 32 | /** 33 | * Usage Demo 34 | */ 35 | var fooId: FooId; 36 | var barId: BarId; 37 | 38 | // Safety! 39 | fooId = barId; // error 40 | barId = fooId; // error 41 | 42 | // Newing up 43 | fooId = 'foo' as FooId; 44 | barId = 'bar' as BarId; 45 | 46 | // Both types are compatible with the base 47 | var str: string; 48 | str = fooId; 49 | str = barId; 50 | } 51 | 52 | namespace Interface { 53 | 54 | // FOO 55 | interface FooId extends String { 56 | _fooIdBrand: string; // To prevent type errors 57 | } 58 | 59 | // BAR 60 | interface BarId extends String { 61 | _barIdBrand: string; // To prevent type errors 62 | } 63 | 64 | /** 65 | * Usage Demo 66 | */ 67 | var fooId: FooId; 68 | var barId: BarId; 69 | 70 | // Safety! 71 | fooId = barId; // error 72 | barId = fooId; // error 73 | fooId = barId; // error 74 | barId = fooId; // error 75 | 76 | // Newing up 77 | fooId = 'foo' as any; 78 | barId = 'bar' as any; 79 | 80 | // If you need the base string 81 | var str: string; 82 | str = fooId as any; 83 | str = barId as any; 84 | } 85 | -------------------------------------------------------------------------------- /code/tips/statefulFunctions.js: -------------------------------------------------------------------------------- 1 | var called = (new (function () { 2 | function class_1() { 3 | var _this = this; 4 | this.count = 0; 5 | this.called = function () { 6 | _this.count++; 7 | console.log("Called : " + _this.count); 8 | }; 9 | } 10 | return class_1; 11 | })()).called; 12 | called(); 13 | called(); 14 | -------------------------------------------------------------------------------- /code/tips/statefulFunctions.ts: -------------------------------------------------------------------------------- 1 | let {called} = new class { 2 | count = 0; 3 | called = () => { 4 | this.count++; 5 | console.log(`Called : ${this.count}`); 6 | } 7 | }; 8 | 9 | called(); // Called : 1 10 | called(); // Called : 2 11 | -------------------------------------------------------------------------------- /code/tips/stringEnums.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var Simple; 3 | (function (Simple) { 4 | var Tristate = { 5 | False: '', 6 | True: '', 7 | Unknown: '' 8 | }; 9 | Object.keys(Tristate).map(function (key) { return Tristate[key] = key; }); 10 | var state = Tristate.True; 11 | if (state === Tristate.True) { 12 | } 13 | })(Simple = exports.Simple || (exports.Simple = {})); 14 | var Fancy; 15 | (function (Fancy) { 16 | var state; 17 | state = 'False'; 18 | })(Fancy = exports.Fancy || (exports.Fancy = {})); 19 | -------------------------------------------------------------------------------- /code/tips/stringEnums.ts: -------------------------------------------------------------------------------- 1 | export namespace Simple { 2 | let Tristate = { 3 | False: '', 4 | True: '', 5 | Unknown: '' 6 | }; 7 | 8 | // make values same as keys 9 | Object.keys(Tristate).map((key) => Tristate[key] = key); 10 | 11 | 12 | /** 13 | * Usage 14 | */ 15 | 16 | // Assigning 17 | let state = Tristate.True; 18 | 19 | // Checking if it matches 20 | if (state === Tristate.True) { 21 | 22 | } 23 | } 24 | 25 | 26 | export namespace Fancy { 27 | type TriState = 'False' | 'True' | 'Unknown'; 28 | 29 | let state: TriState; 30 | state = 'False'; 31 | } 32 | -------------------------------------------------------------------------------- /code/tips/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "declaration": false, 6 | "noImplicitAny": false, 7 | "removeComments": true, 8 | "moduleResolution": "node", 9 | "isolatedModules": false, 10 | "jsx": "react", 11 | "experimentalDecorators": true, 12 | "emitDecoratorMetadata": true, 13 | "noLib": false, 14 | "preserveConstEnums": true, 15 | "suppressImplicitAnyIndexErrors": true 16 | }, 17 | "filesGlob": [ 18 | "**/*.ts", 19 | "**/*.tsx", 20 | "!node_modules/**" 21 | ], 22 | "files": [ 23 | "bindIsBad.ts", 24 | "currying.ts", 25 | "lazyObjectLiteralInitialization.ts", 26 | "mixins.ts", 27 | "nominalTyping.ts", 28 | "statefulFunctions.ts", 29 | "stringEnums.ts" 30 | ], 31 | "exclude": [], 32 | "atom": { 33 | "rewriteTsconfig": true 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /code/types/assertion.js: -------------------------------------------------------------------------------- 1 | exports.asdf = 123; 2 | var porting; 3 | (function (porting) { 4 | var foo = {}; 5 | foo.bar = 123; 6 | foo.bas = 'hello'; 7 | })(porting || (porting = {})); 8 | var assert; 9 | (function (assert) { 10 | var foo = {}; 11 | foo.bar = 123; 12 | foo.bas = 'hello'; 13 | })(assert || (assert = {})); 14 | var sdfsdfsdf; 15 | (function (sdfsdfsdf) { 16 | var foo; 17 | var bar = foo; 18 | })(sdfsdfsdf || (sdfsdfsdf = {})); 19 | var doubleAssertion; 20 | (function (doubleAssertion) { 21 | function handler1(event) { 22 | var mouseEvent = event; 23 | } 24 | function handler2(event) { 25 | var element = event; 26 | } 27 | function handler(event) { 28 | var element = event; 29 | } 30 | })(doubleAssertion || (doubleAssertion = {})); 31 | -------------------------------------------------------------------------------- /code/types/assertion.ts: -------------------------------------------------------------------------------- 1 | export var asdf = 123; 2 | 3 | module porting { 4 | var foo = {}; 5 | foo.bar = 123; // error : property 'bar' does not exist on `{}` 6 | foo.bas = 'hello'; // error : property 'bas' does not exist on `{}` 7 | } 8 | 9 | module assert { 10 | interface Foo { 11 | bar: number; 12 | bas: string; 13 | } 14 | var foo = {} as Foo; 15 | foo.bar = 123; 16 | foo.bas = 'hello'; 17 | } 18 | 19 | module sdfsdfsdf { 20 | var foo: any; 21 | var bar = foo; // bar is now of type "string" 22 | } 23 | 24 | 25 | namespace doubleAssertion { 26 | 27 | function handler1(event: Event) { 28 | let mouseEvent = event as MouseEvent; 29 | } 30 | 31 | function handler2(event: Event) { 32 | let element = event as HTMLElement; // Error : Neither 'Event' not type 'HTMLElement' is assignable to the other 33 | } 34 | 35 | function handler(event: Event) { 36 | let element = event as any as HTMLElement; // Okay! 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /code/types/callable.ts: -------------------------------------------------------------------------------- 1 | export namespace asdfasdfasdfasdflkjasdflkjasdflkjasdflkjasdf { 2 | } 3 | 4 | namespace A { 5 | interface ReturnString { 6 | (): string 7 | } 8 | declare const foo: ReturnString; 9 | const bar = foo(); // bar is inferred as a string 10 | } 11 | 12 | namespace Complex { 13 | interface Complex { 14 | (foo: string, bar?: number, ...others: boolean[]): number; 15 | } 16 | 17 | interface Overloaded { 18 | (foo: string): string 19 | (foo: number): number 20 | } 21 | 22 | // example implementation 23 | const overloaded: Overloaded = (foo) => foo; 24 | 25 | // example usage 26 | const str = overloaded(''); // str is inferred string 27 | const number = overloaded(123); // num is inferred number 28 | } 29 | 30 | namespace Direct { 31 | const overloaded: { 32 | (foo: string): string 33 | (foo: number): number 34 | } = (foo) => foo; 35 | 36 | const simple: (foo: number) => string 37 | = (foo) => foo.toString(); 38 | 39 | interface CallMeWithNewToGetString { 40 | new(): string 41 | } 42 | // Usage 43 | declare const Foo: CallMeWithNewToGetString; 44 | const bar = new Foo(); // bar is inferred to be of type string 45 | } 46 | 47 | -------------------------------------------------------------------------------- /code/types/freshness/freshness.js: -------------------------------------------------------------------------------- 1 | exports.foo = 123; 2 | var first; 3 | (function (first) { 4 | function logName(something) { 5 | console.log(something.name); 6 | } 7 | var person = { name: 'matt', job: 'being awesome' }; 8 | var animal = { name: 'cow', diet: 'vegan, but has milk of own species' }; 9 | var random = { note: "I don't have a name property" }; 10 | logName(person); 11 | logName(animal); 12 | logName(random); 13 | })(first || (first = {})); 14 | var second; 15 | (function (second) { 16 | function logName(something) { 17 | console.log(something.name); 18 | } 19 | logName({ name: 'matt' }); 20 | logName({ name: 'matt', job: 'being awesome' }); 21 | })(second || (second = {})); 22 | var second; 23 | (function (second) { 24 | function logIfHasName(something) { 25 | if (something.name) { 26 | console.log(something.name); 27 | } 28 | } 29 | var person = { name: 'matt', job: 'being awesome' }; 30 | var animal = { name: 'cow', diet: 'vegan, but has milk of own species' }; 31 | var random = { note: "I don't have a name property" }; 32 | logIfHasName(person); 33 | logIfHasName(animal); 34 | logIfHasName(random); 35 | logIfHasName({ neme: 'I just misspelled name to neme' }); 36 | })(second || (second = {})); 37 | -------------------------------------------------------------------------------- /code/types/freshness/freshness.ts: -------------------------------------------------------------------------------- 1 | export var foo = 123; 2 | 3 | 4 | module first { 5 | function logName(something: { name: string }) { 6 | console.log(something.name); 7 | } 8 | 9 | var person = { name: 'matt', job: 'being awesome' }; 10 | var animal = { name: 'cow', diet: 'vegan, but has milk of own species' }; 11 | var random = { note: `I don't have a name property` }; 12 | 13 | logName(person); // okay 14 | logName(animal); // okay 15 | logName(random); // Error : property `name` is missing 16 | } 17 | 18 | module second { 19 | function logName(something: { name: string }) { 20 | console.log(something.name); 21 | } 22 | 23 | logName({ name: 'matt' }); // okay 24 | logName({ name: 'matt', job: 'being awesome' }); // Error: object literals must only specify known properties. `job` is excessive here. 25 | } 26 | 27 | 28 | module second { 29 | function logIfHasName(something: { name?: string }) { 30 | if (something.name) { 31 | console.log(something.name); 32 | } 33 | } 34 | var person = { name: 'matt', job: 'being awesome' }; 35 | var animal = { name: 'cow', diet: 'vegan, but has milk of own species' }; 36 | var random = { note: `I don't have a name property` }; 37 | 38 | logIfHasName(person); // okay 39 | logIfHasName(animal); // okay 40 | logIfHasName(random); // okay 41 | logIfHasName({neme: 'I just misspelled name to neme'}); // Error: object literals must only specify known properties. `neme` is excessive here. 42 | } 43 | -------------------------------------------------------------------------------- /code/types/freshness/index-signatures.js: -------------------------------------------------------------------------------- 1 | var a; 2 | (function (a) { 3 | var foo = {}; 4 | foo['Hello'] = 'World'; 5 | console.log(foo['Hello']); 6 | })(a || (a = {})); 7 | var b; 8 | (function (b) { 9 | var Foo = (function () { 10 | function Foo(message) { 11 | this.message = message; 12 | } 13 | ; 14 | Foo.prototype.log = function () { 15 | console.log(this.message); 16 | }; 17 | return Foo; 18 | }()); 19 | var foo = {}; 20 | foo['Hello'] = new Foo('World'); 21 | foo['Hello'].log(); 22 | })(b || (b = {})); 23 | var c; 24 | (function (c) { 25 | var obj = { 26 | toString: function () { 27 | console.log('toString called'); 28 | return 'Hello'; 29 | } 30 | }; 31 | var foo = {}; 32 | foo[obj] = 'World'; 33 | console.log(foo[obj]); 34 | console.log(foo['Hello']); 35 | })(c || (c = {})); 36 | var d; 37 | (function (d) { 38 | var foo = ['World']; 39 | console.log(foo[0]); 40 | })(d || (d = {})); 41 | var e; 42 | (function (e) { 43 | var obj = { 44 | toString: function () { 45 | return 'Hello'; 46 | } 47 | }; 48 | var foo = {}; 49 | foo[obj] = 'World'; 50 | foo[obj.toString()] = 'World'; 51 | })(e || (e = {})); 52 | var f; 53 | (function (f) { 54 | var obj = { message: 'Hello' }; 55 | var foo = {}; 56 | foo[obj] = 'World'; 57 | console.log(foo["[object Object]"]); 58 | })(f || (f = {})); 59 | var f; 60 | (function (f) { 61 | console.log((1).toString()); 62 | console.log((2).toString()); 63 | })(f || (f = {})); 64 | var g; 65 | (function (g) { 66 | var foo = {}; 67 | foo['a'] = { message: 'some message' }; 68 | foo['a'] = { messages: 'some message' }; 69 | foo['a'].message; 70 | foo['a'].messages; 71 | })(g || (g = {})); 72 | var mustConform2; 73 | (function (mustConform2) { 74 | var foo = { x: 1, y: 2 }; 75 | foo['x']; 76 | var x = 'x'; 77 | foo[x]; 78 | })(mustConform2 || (mustConform2 = {})); 79 | -------------------------------------------------------------------------------- /code/types/freshness/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.5.0-beta", 3 | "compilerOptions": { 4 | "target": "es5", 5 | "module": "commonjs", 6 | "isolatedModules": false, 7 | "jsx": "react", 8 | "experimentalDecorators": true, 9 | "emitDecoratorMetadata": true, 10 | "declaration": false, 11 | "noImplicitAny": false, 12 | "removeComments": true, 13 | "noLib": false, 14 | "preserveConstEnums": true, 15 | "suppressImplicitAnyIndexErrors": true 16 | }, 17 | "filesGlob": [ 18 | "./**/*.ts", 19 | "./**/*.tsx", 20 | "!./node_modules/**/*" 21 | ], 22 | "files": [ 23 | "./freshness.ts", 24 | "./index-signatures.ts" 25 | ], 26 | "atom": { 27 | "rewriteTsconfig": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /code/types/functions.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var parameter; 3 | (function (parameter) { 4 | var sampleVariable; 5 | function foo(sampleParameter) { } 6 | })(parameter || (parameter = {})); 7 | var returnType; 8 | (function (returnType) { 9 | function foo(sample) { 10 | return sample; 11 | } 12 | })(returnType || (returnType = {})); 13 | var inferred; 14 | (function (inferred) { 15 | function foo(sample) { 16 | return sample; 17 | } 18 | })(inferred || (inferred = {})); 19 | var misspelled; 20 | (function (misspelled) { 21 | function foo() { 22 | return { fou: 'John Doe' }; 23 | } 24 | sendAsJSON(foo()); 25 | })(misspelled || (misspelled = {})); 26 | var optional; 27 | (function (optional) { 28 | function foo(bar, bas) { 29 | } 30 | foo(123); 31 | foo(123, 'hello'); 32 | })(optional || (optional = {})); 33 | var optionalDefault; 34 | (function (optionalDefault) { 35 | function foo(bar, bas) { 36 | if (bas === void 0) { bas = 'world'; } 37 | console.log(bar, bas); 38 | } 39 | foo(123); 40 | foo(123, 'hello'); 41 | })(optionalDefault || (optionalDefault = {})); 42 | var overloads; 43 | (function (overloads) { 44 | function padding(a, b, c, d) { 45 | if (b === undefined && c === undefined && d === undefined) { 46 | b = c = d = a; 47 | } 48 | else if (c === undefined && d === undefined) { 49 | c = a; 50 | d = b; 51 | } 52 | return { 53 | top: a, 54 | right: b, 55 | bottom: c, 56 | left: d 57 | }; 58 | } 59 | overloads.padding = padding; 60 | })(overloads || (overloads = {})); 61 | var overloadsDone; 62 | (function (overloadsDone) { 63 | function padding(a, b, c, d) { 64 | if (b === undefined && c === undefined && d === undefined) { 65 | b = c = d = a; 66 | } 67 | else if (c === undefined && d === undefined) { 68 | c = a; 69 | d = b; 70 | } 71 | return { 72 | top: a, 73 | right: b, 74 | bottom: c, 75 | left: d 76 | }; 77 | } 78 | overloadsDone.padding = padding; 79 | })(overloadsDone || (overloadsDone = {})); 80 | -------------------------------------------------------------------------------- /code/types/functions.ts: -------------------------------------------------------------------------------- 1 | export namespace asdfasdfasdfasdflkjasdflkjasdflkjasdflkjasdf { 2 | } 3 | 4 | namespace parameter { 5 | // variable annotation 6 | var sampleVariable: { bar: number } 7 | 8 | // function parameter 9 | function foo(sampleParameter: { bar: number }) { } 10 | } 11 | 12 | namespace returnType { 13 | interface Foo { 14 | foo: string; 15 | } 16 | 17 | // Return type annotated as `: Foo` 18 | function foo(sample: Foo) { 19 | return sample; 20 | } 21 | } 22 | 23 | namespace inferred { 24 | interface Foo { 25 | foo: string; 26 | } 27 | 28 | function foo(sample: Foo) { 29 | return sample; // inferred return type 'Foo' 30 | } 31 | } 32 | 33 | namespace misspelled { 34 | function foo() { 35 | return { fou: 'John Doe' }; // You might not find this misspelling `foo` till its too late 36 | } 37 | 38 | sendAsJSON(foo()); 39 | } 40 | 41 | namespace optional { 42 | function foo(bar: number, bas?: string): void { 43 | // .. 44 | } 45 | 46 | foo(123); 47 | foo(123, 'hello'); 48 | } 49 | 50 | namespace optionalDefault { 51 | function foo(bar: number, bas: string = 'world') { 52 | console.log(bar, bas); 53 | } 54 | 55 | foo(123); // 123, world 56 | foo(123, 'hello'); // 123, hello 57 | } 58 | 59 | namespace overloads { 60 | export function padding(a: number, b?: number, c?: number, d?: any) { 61 | if (b === undefined && c === undefined && d === undefined) { 62 | b = c = d = a; 63 | } 64 | else if (c === undefined && d === undefined) { 65 | c = a; 66 | d = b; 67 | } 68 | return { 69 | top: a, 70 | right: b, 71 | bottom: c, 72 | left: d 73 | }; 74 | } 75 | } 76 | 77 | namespace overloadsDone { 78 | export function padding(all: number); 79 | export function padding(topAndBottom: number, leftAndRight: number); 80 | export function padding(top: number, right: number, bottom: number, left: number); 81 | export function padding(a: number, b?: number, c?: number, d?: number) { 82 | if (b === undefined && c === undefined && d === undefined) { 83 | b = c = d = a; 84 | } 85 | else if (c === undefined && d === undefined) { 86 | c = a; 87 | d = b; 88 | } 89 | return { 90 | top: a, 91 | right: b, 92 | bottom: c, 93 | left: d 94 | }; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /code/types/generics.js: -------------------------------------------------------------------------------- 1 | var aaa; 2 | (function (aaa) { 3 | var Queue = (function () { 4 | function Queue() { 5 | var _this = this; 6 | this.data = []; 7 | this.push = function (item) { return _this.data.push(item); }; 8 | this.pop = function () { return _this.data.shift(); }; 9 | } 10 | return Queue; 11 | }()); 12 | var queue = new Queue(); 13 | queue.push(0); 14 | queue.push("1"); 15 | console.log(queue.pop().toPrecision(1)); 16 | console.log(queue.pop().toPrecision(1)); 17 | })(aaa || (aaa = {})); 18 | var bbb; 19 | (function (bbb) { 20 | var QueueNumber = (function () { 21 | function QueueNumber() { 22 | var _this = this; 23 | this.data = []; 24 | this.push = function (item) { return _this.data.push(item); }; 25 | this.pop = function () { return _this.data.shift(); }; 26 | } 27 | return QueueNumber; 28 | }()); 29 | var queue = new QueueNumber(); 30 | queue.push(0); 31 | queue.push("1"); 32 | })(bbb || (bbb = {})); 33 | var ccc; 34 | (function (ccc) { 35 | var Queue = (function () { 36 | function Queue() { 37 | var _this = this; 38 | this.data = []; 39 | this.push = function (item) { return _this.data.push(item); }; 40 | this.pop = function () { return _this.data.shift(); }; 41 | } 42 | return Queue; 43 | }()); 44 | var queue = new Queue(); 45 | queue.push(0); 46 | queue.push("1"); 47 | })(ccc || (ccc = {})); 48 | -------------------------------------------------------------------------------- /code/types/generics.ts: -------------------------------------------------------------------------------- 1 | module aaa { 2 | class Queue { 3 | private data = []; 4 | push = (item) => this.data.push(item); 5 | pop = () => this.data.shift(); 6 | } 7 | 8 | const queue = new Queue(); 9 | queue.push(0); 10 | queue.push("1"); // Oops a mistake 11 | 12 | // a developer walks into a bar 13 | console.log(queue.pop().toPrecision(1)); 14 | console.log(queue.pop().toPrecision(1)); // RUNTIME ERROR 15 | } 16 | 17 | module bbb { 18 | class QueueNumber { 19 | private data = []; 20 | push = (item: number) => this.data.push(item); 21 | pop = (): number => this.data.shift(); 22 | } 23 | 24 | const queue = new QueueNumber(); 25 | queue.push(0); 26 | queue.push("1"); // ERROR : cannot push a string. Only numbers allowed 27 | 28 | // ^ if that error is fixed the rest would be fine too 29 | } 30 | 31 | module ccc { 32 | /** A class definition with a generic parameter */ 33 | class Queue { 34 | private data = []; 35 | push = (item: T) => this.data.push(item); 36 | pop = (): T => this.data.shift(); 37 | } 38 | 39 | /** Again sample usage */ 40 | const queue = new Queue(); 41 | queue.push(0); 42 | queue.push("1"); // ERROR : cannot push a string. Only numbers allowed 43 | 44 | // ^ if that error is fixed the rest would be fine too 45 | } 46 | 47 | namespace ddd { 48 | const getJSON = (config: { 49 | url: string, 50 | headers?: { [key: string]: string }, 51 | }): Promise => { 52 | const fetchConfig = ({ 53 | method: 'GET', 54 | 'Accept': 'application/json', 55 | 'Content-Type': 'application/json', 56 | ...(config.headers || {}) 57 | }); 58 | return fetch(config.url, fetchConfig) 59 | .then(response => response.json()); 60 | } 61 | 62 | type LoadUsersResponse = { 63 | users: { 64 | name: string; 65 | email: string; 66 | }[]; 67 | }; 68 | function loadUsers() { 69 | return getJSON({ url: 'https://example.com/users' }); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /code/types/interfaces.js: -------------------------------------------------------------------------------- 1 | var Implement; 2 | (function (Implement) { 3 | var MyPoint = (function () { 4 | function MyPoint() { 5 | } 6 | return MyPoint; 7 | }()); 8 | })(Implement || (Implement = {})); 9 | var ErrorIt; 10 | (function (ErrorIt) { 11 | var MyPoint = (function () { 12 | function MyPoint() { 13 | } 14 | return MyPoint; 15 | }()); 16 | })(ErrorIt || (ErrorIt = {})); 17 | -------------------------------------------------------------------------------- /code/types/interfaces.ts: -------------------------------------------------------------------------------- 1 | namespace Implement { 2 | interface Point { 3 | x: number; y: number; 4 | } 5 | 6 | class MyPoint implements Point { 7 | x: number; y: number; // Same as Point 8 | } 9 | } 10 | 11 | namespace ErrorIt { 12 | interface Point { 13 | x: number; y: number; 14 | z: number; // New member 15 | } 16 | 17 | class MyPoint implements Point { // ERROR : missing member `z` 18 | x: number; y: number; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /code/types/keyof.ts: -------------------------------------------------------------------------------- 1 | namespace Test { 2 | const colors = { 3 | red: 'red', 4 | blue: 'blue' 5 | } 6 | type Colors = keyof typeof colors; 7 | 8 | let color: Colors; 9 | color = 'red'; // okay 10 | color = 'blue'; // okay 11 | color = 'blue'; // Error 12 | } -------------------------------------------------------------------------------- /code/types/lib/exclude/nolibd.js: -------------------------------------------------------------------------------- 1 | var foo = 123; 2 | var bar = foo.toString(); 3 | -------------------------------------------------------------------------------- /code/types/lib/exclude/nolibd.ts: -------------------------------------------------------------------------------- 1 | var foo = 123; 2 | var bar = foo.toString(); // Property 'toString' does not exist on type 'number'. -------------------------------------------------------------------------------- /code/types/lib/exclude/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions":{ 3 | "noLib": true 4 | } 5 | } -------------------------------------------------------------------------------- /code/types/lib/usage/libd.js: -------------------------------------------------------------------------------- 1 | var foo = 123; 2 | var bar = foo.toString(); 3 | var test = window; 4 | window.helloWorld = function () { return console.log('hello world'); }; 5 | window.helloWorld(); 6 | Math.seedrandom(); 7 | Date.parse; 8 | String.prototype.endsWith = function (suffix) { 9 | var str = this; 10 | return str && str.indexOf(suffix, str.length - suffix.length) !== -1; 11 | }; 12 | console.log('foo bar'.endsWith('bas')); 13 | console.log('foo bas'.endsWith('bas')); 14 | -------------------------------------------------------------------------------- /code/types/lib/usage/libd.ts: -------------------------------------------------------------------------------- 1 | var foo = 123; 2 | var bar = foo.toString(); 3 | 4 | var test = window; 5 | 6 | interface Window { 7 | helloWorld(): void; 8 | } 9 | 10 | // Add it at runtime 11 | window.helloWorld = () => console.log('hello world'); 12 | // Call it 13 | window.helloWorld(); 14 | // Misuse it and you get an error: 15 | // window.helloWorld('gracius'); // Error: Supplied parameters do not match the signature of the call target 16 | 17 | 18 | interface Math { 19 | seedrandom(seed?: string); 20 | } 21 | 22 | Math.seedrandom(); 23 | 24 | Date.parse 25 | interface Date { 26 | 27 | } 28 | 29 | interface String { 30 | endsWith(suffix: string): boolean; 31 | } 32 | 33 | String.prototype.endsWith = function(suffix: string): boolean { 34 | var str: string = this; 35 | return str && str.indexOf(suffix, str.length - suffix.length) !== -1; 36 | } 37 | 38 | console.log('foo bar'.endsWith('bas')); // false 39 | console.log('foo bas'.endsWith('bas')); // true -------------------------------------------------------------------------------- /code/types/lib/usage/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions":{ 3 | } 4 | } -------------------------------------------------------------------------------- /code/types/libd.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melissarofman/typescript-book/aa9ca251cb7b4616183c0e2045a48a581d1d83c0/code/types/libd.js -------------------------------------------------------------------------------- /code/types/literal-types.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var Simple; 3 | (function (Simple) { 4 | var foo; 5 | foo = 'Bar'; 6 | })(Simple = exports.Simple || (exports.Simple = {})); 7 | var Union; 8 | (function (Union) { 9 | function move(distance, direction) { 10 | } 11 | move(1, "North"); 12 | move(1, "Nurth"); 13 | })(Union = exports.Union || (exports.Union = {})); 14 | -------------------------------------------------------------------------------- /code/types/literal-types.ts: -------------------------------------------------------------------------------- 1 | export namespace Simple { 2 | let foo: 'Hello'; 3 | foo = 'Bar'; // Error: "Bar" is not assignable to type "Hello" 4 | } 5 | 6 | 7 | export namespace Union { 8 | type CardinalDirection = 9 | "North" 10 | | "East" 11 | | "South" 12 | | "West"; 13 | 14 | function move(distance: number, direction: CardinalDirection) { 15 | // ... 16 | } 17 | 18 | move(1, "North"); // Okay 19 | move(1, "Nurth"); // Error! 20 | } 21 | 22 | namespace StringEnum { 23 | 24 | /** Utility function to create a K:V from a list of strings */ 25 | function strEnum(o: Array): {[K in T]: K} { 26 | return o.reduce((res, key) => { 27 | res[key] = key; 28 | return res; 29 | }, Object.create(null)); 30 | } 31 | 32 | /** 33 | * Sample create a string enum 34 | */ 35 | 36 | /** Create a K:V */ 37 | const Direction = strEnum([ 38 | 'North', 39 | 'South', 40 | 'East', 41 | 'West' 42 | ]) 43 | /** Create a Type */ 44 | type Direction = keyof typeof Direction; 45 | 46 | /** 47 | * Sample using a string enum 48 | */ 49 | let sample: Direction; 50 | 51 | sample = Direction.North; // Okay 52 | sample = 'North'; // Okay 53 | sample = 'AnythingElse'; // ERROR! 54 | } -------------------------------------------------------------------------------- /code/types/migrating/migrating.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melissarofman/typescript-book/aa9ca251cb7b4616183c0e2045a48a581d1d83c0/code/types/migrating/migrating.js -------------------------------------------------------------------------------- /code/types/migrating/migrating.ts: -------------------------------------------------------------------------------- 1 | declare var $: any; 2 | declare type JQuery = any; -------------------------------------------------------------------------------- /code/types/migrating/tsconfig.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /code/types/stringLiteralType.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var Simple; 3 | (function (Simple) { 4 | var foo; 5 | foo = 'Bar'; 6 | })(Simple = exports.Simple || (exports.Simple = {})); 7 | var Union; 8 | (function (Union) { 9 | function move(distance, direction) { 10 | } 11 | move(1, "North"); 12 | move(1, "Nurth"); 13 | })(Union = exports.Union || (exports.Union = {})); 14 | -------------------------------------------------------------------------------- /code/types/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "isolatedModules": false, 7 | "jsx": "react", 8 | "experimentalDecorators": true, 9 | "emitDecoratorMetadata": true, 10 | "declaration": false, 11 | "noImplicitAny": false, 12 | "removeComments": true, 13 | "noLib": false, 14 | "preserveConstEnums": true, 15 | "suppressImplicitAnyIndexErrors": true 16 | }, 17 | "include": [ 18 | "./**/*.ts", 19 | "./**/*.tsx" 20 | ], 21 | "atom": { 22 | "rewriteTsconfig": false 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /code/types/typeGuard.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var quick; 3 | (function (quick) { 4 | function doSomething(x) { 5 | if (typeof x === 'string') { 6 | console.log(x.subtr(1)); 7 | console.log(x.substr(1)); 8 | } 9 | x.substr(1); 10 | } 11 | })(quick = exports.quick || (exports.quick = {})); 12 | var instance; 13 | (function (instance) { 14 | var Foo = (function () { 15 | function Foo() { 16 | this.foo = 123; 17 | this.common = '123'; 18 | } 19 | return Foo; 20 | }()); 21 | var Bar = (function () { 22 | function Bar() { 23 | this.bar = 123; 24 | this.common = '123'; 25 | } 26 | return Bar; 27 | }()); 28 | function doStuff(arg) { 29 | if (arg instanceof Foo) { 30 | console.log(arg.foo); 31 | console.log(arg.bar); 32 | } 33 | if (arg instanceof Bar) { 34 | console.log(arg.foo); 35 | console.log(arg.bar); 36 | } 37 | console.log(arg.common); 38 | console.log(arg.foo); 39 | console.log(arg.bar); 40 | } 41 | doStuff(new Foo()); 42 | doStuff(new Bar()); 43 | })(instance = exports.instance || (exports.instance = {})); 44 | var instanceElse; 45 | (function (instanceElse) { 46 | var Foo = (function () { 47 | function Foo() { 48 | this.foo = 123; 49 | } 50 | return Foo; 51 | }()); 52 | var Bar = (function () { 53 | function Bar() { 54 | this.bar = 123; 55 | } 56 | return Bar; 57 | }()); 58 | function doStuff(arg) { 59 | if (arg instanceof Foo) { 60 | console.log(arg.foo); 61 | console.log(arg.bar); 62 | } 63 | else { 64 | console.log(arg.foo); 65 | console.log(arg.bar); 66 | } 67 | } 68 | doStuff(new Foo()); 69 | doStuff(new Bar()); 70 | })(instanceElse = exports.instanceElse || (exports.instanceElse = {})); 71 | var userDefined; 72 | (function (userDefined) { 73 | function isFoo(arg) { 74 | return arg.foo !== undefined; 75 | } 76 | function doStuff(arg) { 77 | if (isFoo(arg)) { 78 | console.log(arg.foo); 79 | console.log(arg.bar); 80 | } 81 | else { 82 | console.log(arg.foo); 83 | console.log(arg.bar); 84 | } 85 | } 86 | doStuff({ foo: 123, common: '123' }); 87 | doStuff({ bar: 123, common: '123' }); 88 | })(userDefined = exports.userDefined || (exports.userDefined = {})); 89 | -------------------------------------------------------------------------------- /cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melissarofman/typescript-book/aa9ca251cb7b4616183c0e2045a48a581d1d83c0/cover.jpg -------------------------------------------------------------------------------- /docs/compiler-options.md: -------------------------------------------------------------------------------- 1 | // mention Pinned comments 2 | 3 | ```ts 4 | /*! 5 | * License 6 | */ 7 | ``` 8 | -------------------------------------------------------------------------------- /docs/compiler/ast-tip-children.md: -------------------------------------------------------------------------------- 1 | ### AST Tip: Visit Children 2 | 3 | There is a utility function `ts.forEachChild` that allows you to visit all the child nodes of any Node in the AST. 4 | 5 | Here is simplified snippet of the source code to demonstrate how it functions: 6 | 7 | ```ts 8 | 9 | export function forEachChild(node: Node, cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T { 10 | if (!node) { 11 | return; 12 | } 13 | switch (node.kind) { 14 | case SyntaxKind.BinaryExpression: 15 | return visitNode(cbNode, (node).left) || 16 | visitNode(cbNode, (node).operatorToken) || 17 | visitNode(cbNode, (node).right); 18 | case SyntaxKind.IfStatement: 19 | return visitNode(cbNode, (node).expression) || 20 | visitNode(cbNode, (node).thenStatement) || 21 | visitNode(cbNode, (node).elseStatement); 22 | 23 | // .... lots more 24 | ``` 25 | 26 | Basically, it checks `node.kind` and based on that assumes an interface offered by the `node` and calls the `cbNode` on the children. However, note that this function doesn't call `visitNode` for *all* children (e.g. SyntaxKind.SemicolonToken). If you want *all* the children of a node in the AST just call `.getChildren` member function of the `Node`. 27 | 28 | E.g. here is a function that prints the verbose `AST` of a node: 29 | 30 | ```ts 31 | function printAllChildren(node: ts.Node, depth = 0) { 32 | console.log(new Array(depth+1).join('----'), ts.syntaxKindToName(node.kind), node.pos, node.end); 33 | depth++; 34 | node.getChildren().forEach(c=> printAllChildren(c, depth)); 35 | } 36 | ``` 37 | 38 | We will see a sample usage of this function when we discuss the parser further. 39 | -------------------------------------------------------------------------------- /docs/compiler/ast-tip-syntaxkind.md: -------------------------------------------------------------------------------- 1 | ### AST Tip: SyntaxKind 2 | 3 | `SyntaxKind` is defined as a `const enum`, here is a sample: 4 | 5 | ```ts 6 | export const enum SyntaxKind { 7 | Unknown, 8 | EndOfFileToken, 9 | SingleLineCommentTrivia, 10 | // ... LOTS more 11 | ``` 12 | 13 | It's a `const enum` (a concept [we covered previously](../enums.md)) so that it gets *inlined* (e.g. `ts.SyntaxKind.EndOfFileToken` becomes `1`) and we don't get a dereferencing cost when working with the AST. However, the compiler is compiled with `--preserveConstEnums` compiler flag so that the enum *is still available at runtime*. So in JavaScript you can use `ts.SyntaxKind.EndOfFileToken` if you want. Additionally you can convert these enum members to display strings using the following function: 14 | 15 | ```ts 16 | export function syntaxKindToName(kind: ts.SyntaxKind) { 17 | return (ts).SyntaxKind[kind]; 18 | } 19 | ``` 20 | -------------------------------------------------------------------------------- /docs/compiler/ast-trivia.md: -------------------------------------------------------------------------------- 1 | ### Trivia 2 | Trivia (called that because it's `trivial`) represent the parts of the source text that are largely insignificant for normal understanding of the code. For example; whitespace, comments, and even conflict markers. Trivia is *not stored* in the AST (to keep it lightweight). However, it can be fetched *on demand* using a few `ts.*` APIs. 3 | 4 | Before we show them you need to understand the following: 5 | 6 | #### Trivia Ownership 7 | In General: 8 | * A token owns any trivia after it on the *same* line *upto* the next token. 9 | * Any comment *after that line* is associated with the following token. 10 | 11 | For leading and ending comments in a file: 12 | * The first token in the source file gets all the initial trivia. 13 | * The last sequence of trivia in the file is tacked onto the end-of-file token, which otherwise has zero width. 14 | 15 | #### Trivia APIs 16 | For most basic uses, comments are the "interesting" trivia. The comments that belong to a Node can be fetched through the following functions: 17 | 18 | Function | Description 19 | ---------|------------ 20 | `ts.getLeadingCommentRanges` | Given the source text and position within that text, returns ranges of comments between the first line break following the given position and the token itself (probably most useful with `ts.Node.getFullStart`). 21 | `ts.getTrailingCommentRanges` | Given the source text and position within that text, returns ranges of comments until the first line break following the given position (probably most useful with `ts.Node.getEnd`). 22 | 23 | As an example, imagine this portion of a source file: 24 | 25 | ```ts 26 | debugger;/*hello*/ 27 | //bye 28 | /*hi*/ function 29 | ``` 30 | 31 | `getLeadingCommentRanges` for the `function` will only return the last 2 comments `//bye` and `/*hi*/`. 32 | 33 | Appropriately, calling `getTrailingCommentRanges` on the end of the debugger statement will extract the `/*hello*/` comment. 34 | 35 | #### Token Start/Full Start 36 | Nodes have what is called a "token start" and a "full start". 37 | 38 | * Token Start: the more natural version, which is the position in file where the text of a token begins 39 | * Full Start: the point at which the scanner began scanning since the last significant token 40 | 41 | AST nodes have an API for `getStart` and `getFullStart`. In the following example: 42 | 43 | ```ts 44 | debugger;/*hello*/ 45 | //bye 46 | /*hi*/ function 47 | ``` 48 | for `function` the token start is at `function` whereas *full* start is at `/*hello*/`. Note that full start even includes the trivia that would otherwise be owned by the previous node. 49 | -------------------------------------------------------------------------------- /docs/compiler/ast.md: -------------------------------------------------------------------------------- 1 | ## Node 2 | The basic building block of the Abstract Syntax Tree (AST). In general a `Node` represents non-terminals in the language grammar; however, some terminals are kept in the tree such as identifiers and literals. 3 | 4 | Two key things make up an AST node's documentation. The node's `SyntaxKind` which identifies its type within the AST, and its `interface`, the API the node provides when instantiated into the AST. 5 | 6 | Here are a few key `interface Node` members: 7 | * `TextRange` members that identify the node's `start` and `end` in the source file. 8 | * `parent?: Node` the parent of the node in the AST. 9 | 10 | There are other additional members for `Node` flags and modifiers etc. that you can lookup by searching `interface Node` in the source code but the ones we mentioned are vital for node traversal. 11 | 12 | ## SourceFile 13 | 14 | * `SyntaxKind.SourceFile` 15 | * `interface SourceFile`. 16 | 17 | Each `SourceFile` is a top-level AST node that is contained in the `Program`. 18 | -------------------------------------------------------------------------------- /docs/compiler/binder-declarations.md: -------------------------------------------------------------------------------- 1 | ### Symbols and Declarations 2 | Linking between a `node` and a `symbol` is performed by a few functions. One function that is used to bind the `SourceFile` node to the source file Symbol (in case of an external module) is the `addDeclarationToSymbol` function 3 | 4 | Note : the `Symbol` for an external module source file is setup as `flags : SymbolFlags.ValueModule` and `name: '"' + removeFileExtension(file.fileName) + '"'`). 5 | 6 | ```ts 7 | function addDeclarationToSymbol(symbol: Symbol, node: Declaration, symbolFlags: SymbolFlags) { 8 | symbol.flags |= symbolFlags; 9 | 10 | node.symbol = symbol; 11 | 12 | if (!symbol.declarations) { 13 | symbol.declarations = []; 14 | } 15 | symbol.declarations.push(node); 16 | 17 | if (symbolFlags & SymbolFlags.HasExports && !symbol.exports) { 18 | symbol.exports = {}; 19 | } 20 | 21 | if (symbolFlags & SymbolFlags.HasMembers && !symbol.members) { 22 | symbol.members = {}; 23 | } 24 | 25 | if (symbolFlags & SymbolFlags.Value && !symbol.valueDeclaration) { 26 | symbol.valueDeclaration = node; 27 | } 28 | } 29 | ``` 30 | 31 | The important linking portions: 32 | * Creates a link to the Symbol from the AST node (`node.symbol`). 33 | * Adds the node as *one of* the declarations of the Symbol (`symbol.declarations`). 34 | 35 | #### Declaration 36 | Declaration is just a `node` with an optional name. In `types.ts` 37 | 38 | ```ts 39 | interface Declaration extends Node { 40 | _declarationBrand: any; 41 | name?: DeclarationName; 42 | } 43 | ``` 44 | -------------------------------------------------------------------------------- /docs/compiler/binder-diagnostics.md: -------------------------------------------------------------------------------- 1 | ### Binder Error Reporting 2 | 3 | Binding errors are added to the sourceFile's list of `bindDiagnostics`. 4 | 5 | An example error detected during binding is the use of `eval` or `arguments` as a variable name in `use strict` scenario. The relevant code is presented in its entirety below (`checkStrictModeEvalOrArguments` is called from multiple places, call stacks originating from `bindWorker` which calls different functions for different node `SyntaxKind`): 6 | 7 | ```ts 8 | function checkStrictModeEvalOrArguments(contextNode: Node, name: Node) { 9 | if (name && name.kind === SyntaxKind.Identifier) { 10 | let identifier = name; 11 | if (isEvalOrArgumentsIdentifier(identifier)) { 12 | // We check first if the name is inside class declaration or class expression; if so give explicit message 13 | // otherwise report generic error message. 14 | let span = getErrorSpanForNode(file, name); 15 | file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, 16 | getStrictModeEvalOrArgumentsMessage(contextNode), identifier.text)); 17 | } 18 | } 19 | } 20 | 21 | function isEvalOrArgumentsIdentifier(node: Node): boolean { 22 | return node.kind === SyntaxKind.Identifier && 23 | ((node).text === "eval" || (node).text === "arguments"); 24 | } 25 | 26 | function getStrictModeEvalOrArgumentsMessage(node: Node) { 27 | // Provide specialized messages to help the user understand why we think they're in 28 | // strict mode. 29 | if (getContainingClass(node)) { 30 | return Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode; 31 | } 32 | 33 | if (file.externalModuleIndicator) { 34 | return Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode; 35 | } 36 | 37 | return Diagnostics.Invalid_use_of_0_in_strict_mode; 38 | } 39 | ``` 40 | -------------------------------------------------------------------------------- /docs/compiler/binder-functions.md: -------------------------------------------------------------------------------- 1 | ### Binder function 2 | Two critical binder functions are `bindSourceFile` and `mergeSymbolTable`. We will take a look at these next. 3 | 4 | #### `bindSourceFile` 5 | Basically checks if `file.locals` is defined, if not it hands over to (a local function) `bind`. 6 | 7 | Note: `locals` is defined on `Node` and is of type `SymbolTable`. Note that `SourceFile` is also a `Node` (in fact a root node in the AST). 8 | 9 | TIP: local functions are used heavily within the TypeScript compiler. A local function very likely uses variables from the parent function (captured by closure). In the case of `bind` (a local function within `bindSourceFile`) it (or a function it calls) will setup the `symbolCount` and `classifiableNames` among others, that are then stored on the returned `SourceFile`. 10 | 11 | #### `bind` 12 | Bind takes any `Node` (not just `SourceFile`). First thing it does is assign the `node.parent` (if `parent` variable has been setup ... which again is something the binder does during its processing within the `bindChildren` function), then hands off to `bindWorker` which does the *heavy* lifting. Finally it calls `bindChildren` (a function that simply stores the binder state e.g. current `parent` within its function local vars, then calls `bind` on each child, and then restores the binder state). Now let's look at `bindWorker` which is the more interesting function. 13 | 14 | #### `bindWorker` 15 | This function switches on `node.kind` (of type `SyntaxKind`) and delegates work to the appropriate `bindFoo` function (also defined within `binder.ts`). For example if the `node` is a `SourceFile` it calls (eventually and only if its an external file module) `bindAnonymousDeclaration` 16 | 17 | #### `bindFoo` functions 18 | There are a few patterns common to `bindFoo` functions as well as some utility functions that these use. One function that is almost always used is the `createSymbol` function. It is presented in its entirety below: 19 | 20 | ```ts 21 | function createSymbol(flags: SymbolFlags, name: string): Symbol { 22 | symbolCount++; 23 | return new Symbol(flags, name); 24 | } 25 | ``` 26 | As you can see it is simply keeping the `symbolCount` (a local to `bindSourceFile`) up to date and creating the symbol with the specified parameters. 27 | -------------------------------------------------------------------------------- /docs/compiler/binder.md: -------------------------------------------------------------------------------- 1 | ## Binder 2 | Most JavaScript transpilers out there are simpler than TypeScript because they provide little in the way of code analysis. The typical JavaScript transpilers only have the following flow: 3 | 4 | ```ts 5 | SourceCode ~~Scanner~~> Tokens ~~Parser~~> AST ~~Emitter~~> JavaScript 6 | ``` 7 | 8 | While the above architecture is true as a simplified understanding of TypeScript js generation, a key feature of TypeScript is its *Semantic* system. In order to assist type checking (performed by the `checker`), the `binder` (in `binder.ts`) is used to connect the various parts of the source code into a coherent type system that can then be used by the `checker`. The main responsibility of the binder is to create _Symbols_. 9 | 10 | ### Symbol 11 | Symbols connect declaration nodes in the AST to other declarations contributing to the same entity. Symbols are the basic building blocks of the Semantic system. The symbol constructor is defined in `core.ts` (and `binder` actually uses the `objectAllocator.getSymbolConstructor` to get its hands on it). Here is the symbol constructor: 12 | 13 | ```ts 14 | function Symbol(flags: SymbolFlags, name: string) { 15 | this.flags = flags; 16 | this.name = name; 17 | this.declarations = undefined; 18 | } 19 | ``` 20 | 21 | `SymbolFlags` is a flag enum and is really used to identify additional classifications of the symbol (e.g. variable scope flags `FunctionScopedVariable` or `BlockScopedVariable` among others) 22 | 23 | ### Usage by Checker 24 | The `binder` is actually used internally by the type `checker` which in turn is used by the `program`. The simplified call stack looks like: 25 | ``` 26 | program.getTypeChecker -> 27 | ts.createTypeChecker (in checker)-> 28 | initializeTypeChecker (in checker) -> 29 | for each SourceFile `ts.bindSourceFile` (in binder) 30 | // followed by 31 | for each SourceFile `ts.mergeSymbolTable` (in checker) 32 | ``` 33 | The unit of work for the binder is a SourceFile. The `binder.ts` is driven by `checker.ts`. 34 | -------------------------------------------------------------------------------- /docs/compiler/checker-diagnostics.md: -------------------------------------------------------------------------------- 1 | ### Checker error reporting 2 | The checker uses the local `error` function to report errors. Here is the function: 3 | 4 | ```ts 5 | function error(location: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): void { 6 | let diagnostic = location 7 | ? createDiagnosticForNode(location, message, arg0, arg1, arg2) 8 | : createCompilerDiagnostic(message, arg0, arg1, arg2); 9 | diagnostics.add(diagnostic); 10 | } 11 | ``` 12 | -------------------------------------------------------------------------------- /docs/compiler/checker-global.md: -------------------------------------------------------------------------------- 1 | ### Global Namespace Merging 2 | Within `initializeTypeChecker` the following code exists: 3 | 4 | ```ts 5 | // Initialize global symbol table 6 | forEach(host.getSourceFiles(), file => { 7 | if (!isExternalModule(file)) { 8 | mergeSymbolTable(globals, file.locals); 9 | } 10 | }); 11 | ``` 12 | 13 | Which basically merges all the `global` symbols into the `let globals: SymbolTable = {};` (in `createTypeChecker`) SymbolTable. `mergeSymbolTable` primarily calls `mergeSymbol`. 14 | -------------------------------------------------------------------------------- /docs/compiler/checker.md: -------------------------------------------------------------------------------- 1 | ## Checker 2 | Like we mentioned before *checker* is the thing that makes TypeScript uniquely more powerful than *just another JavaScript transpiler*. The checker is located in `checker.ts` and at this moment it is 23k+ lines of TypeScript (largest part of the compiler). 3 | 4 | ### Usage by Program 5 | The `checker` is initialized by `program`. The following is a sampling of the call stack (we showed the same one when looking at `binder`): 6 | 7 | ``` 8 | program.getTypeChecker -> 9 | ts.createTypeChecker (in checker)-> 10 | initializeTypeChecker (in checker) -> 11 | for each SourceFile `ts.bindSourceFile` (in binder) 12 | // followed by 13 | for each SourceFile `ts.mergeSymbolTable` (in checker) 14 | ``` 15 | 16 | ### Association with Emitter 17 | True type checking happens once a call is made to `getDiagnostics`. This function is called e.g. once a request is made to `Program.emit`, in which case the checker returns an `EmitResolver` (program calls the checkers `getEmitResolver` function) which is just a set of functions local to `createTypeChecker`. We will mention this again when we look at the emitter. 18 | 19 | Here is the call stack right down to `checkSourceFile` (a function local to `createTypeChecker`). 20 | 21 | ``` 22 | program.emit -> 23 | emitWorker (program local) -> 24 | createTypeChecker.getEmitResolver -> 25 | // First call the following functions local to createTypeChecker 26 | call getDiagnostics -> 27 | getDiagnosticsWorker -> 28 | checkSourceFile 29 | 30 | // then 31 | return resolver 32 | (already initialized in createTypeChecker using a call to local createResolver()) 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/compiler/emitter.md: -------------------------------------------------------------------------------- 1 | ## Emitter 2 | There are two `emitters` provided with the TypeScript compiler: 3 | 4 | * `emitter.ts`: this is the emitter you are most likely to be interested in. Its the TS -> JavaScript emitter. 5 | * `declarationEmitter.ts`: this is the emitter used to create a *declaration file* (a `.d.ts`) for a *TypeScript source file* (a `.ts` file). 6 | 7 | We will look at `emitter.ts` in this section. 8 | 9 | ### Usage by `program` 10 | Program provides an `emit` function. This function primarily delegates to `emitFiles` function in `emitter.ts`. Here is the call stack: 11 | 12 | ``` 13 | Program.emit -> 14 | `emitWorker` (local in program.ts createProgram) -> 15 | `emitFiles` (function in emitter.ts) 16 | ``` 17 | One thing that the `emitWorker` provides to the emitter (via an argument to `emitFiles`) is an `EmitResolver`. `EmitResolver` is provided by the program's TypeChecker, basically it is a subset of *local* functions from `createChecker`. 18 | -------------------------------------------------------------------------------- /docs/compiler/make-global.md: -------------------------------------------------------------------------------- 1 | ## Make TypeScript Global 2 | 3 | TypeScript is written using a `namespace ts`. And then the whole compiler is compiled into a single `typescript.js` file. If you want to copy over parts of the source code for exploration a great way to do that is to copy over the portions that you are exploring and then expose them to the global variable `ts`. 4 | 5 | A great way to play around with the TypeScript compiler is just to copy the TypeScript compiler source into a folder and then reference it as a `global` variable. 6 | -------------------------------------------------------------------------------- /docs/compiler/parser.md: -------------------------------------------------------------------------------- 1 | ## Parser 2 | The sourcecode for the TypeScript parser is located entirely in `parser.ts`. Scanner is *controlled* internally by the `Parser` to convert the source code to an AST. Here is a review of what the desired outcome is. 3 | 4 | ``` 5 | SourceCode ~~ scanner ~~> Token Stream ~~ parser ~~> AST 6 | ``` 7 | 8 | The parser is implemented as a singleton (similar reasons to `scanner`, don't want to recreate it if we can reinit it). It is actually implemented as `namespace Parser` which contains *state* variables for the Parser as well as a singleton `scanner`. As mentioned before it contains a `const scanner`. The parser functions manage this scanner. 9 | 10 | ### Usage by program 11 | Parser is driven indirectly by Program (indirectly as its actually by `CompilerHost` which we mentioned previously). Basically this is the simplified call stack: 12 | 13 | ``` 14 | Program -> 15 | CompilerHost.getSourceFile -> 16 | (global function parser.ts).createSourceFile -> 17 | Parser.parseSourceFile 18 | ``` 19 | 20 | The `parseSourceFile` not only primes the state for the Parser but also primes the state for the `scanner` by calling `initializeState`. It then goes on to parse the source file using `parseSourceFileWorker`. 21 | 22 | ### Sample Usage 23 | Before we dig too deep into the parser internals, here is a sample code that uses the TypeScript's parser to get the AST of a source file (using `ts.createSourceFile`), and then print it. 24 | 25 | `code/compiler/parser/runParser.ts` 26 | ```ts 27 | import * as ts from "ntypescript"; 28 | 29 | function printAllChildren(node: ts.Node, depth = 0) { 30 | console.log(new Array(depth + 1).join('----'), ts.formatSyntaxKind(node.kind), node.pos, node.end); 31 | depth++; 32 | node.getChildren().forEach(c=> printAllChildren(c, depth)); 33 | } 34 | 35 | var sourceCode = ` 36 | var foo = 123; 37 | `.trim(); 38 | 39 | var sourceFile = ts.createSourceFile('foo.ts', sourceCode, ts.ScriptTarget.ES5, true); 40 | printAllChildren(sourceFile); 41 | ``` 42 | 43 | This will print out the following: 44 | 45 | ```ts 46 | SourceFile 0 14 47 | ---- SyntaxList 0 14 48 | -------- VariableStatement 0 14 49 | ------------ VariableDeclarationList 0 13 50 | ---------------- VarKeyword 0 3 51 | ---------------- SyntaxList 3 13 52 | -------------------- VariableDeclaration 3 13 53 | ------------------------ Identifier 3 7 54 | ------------------------ FirstAssignment 7 9 55 | ------------------------ FirstLiteralToken 9 13 56 | ------------ SemicolonToken 13 14 57 | ---- EndOfFileToken 14 14 58 | ``` 59 | This looks like a (very right sided) tree if you tilt your head to the left. 60 | -------------------------------------------------------------------------------- /docs/compiler/program.md: -------------------------------------------------------------------------------- 1 | ## Program 2 | 3 | Defined in `program.ts`. The compilation context ([a concept we covered previously](../project/compilation-context.md)) is represented within the TypeScript compiler as a `Program`. It consists of `SourceFile`s and compiler options. 4 | 5 | 6 | ### Usage of `CompilerHost` 7 | Its interaction mechanism with the OE: 8 | 9 | `Program` *-uses->* `CompilerHost` *-uses->* `System` 10 | 11 | The reason for having a `CompilerHost` as a point of indirection is that it allows its interface to be more finely tuned for `Program` needs and not bother with OE needs (e.g. the `Program` doesn't care about `fileExists` a function provided by `System`). 12 | 13 | There are other users of `System` as well (e.g. tests). 14 | 15 | ### SourceFile 16 | 17 | The program provides an API to get the Source Files `getSourceFiles(): SourceFile[];`. Each is represented as a root-level node for an AST (called `SourceFile`). 18 | -------------------------------------------------------------------------------- /docs/const.md: -------------------------------------------------------------------------------- 1 | ### const 2 | 3 | `const` es una adición ofrecida por ES6 / TypeSCript muy bienvenida. Permite la inmutabilidad con variables. Esto es bueno tanto desde una perspectiva de documentación como de tiempo de ejecución. Para usar const, simplemente reemplazá `var` con `const`: 4 | 5 | ```ts 6 | const foo = 123; 7 | ``` 8 | 9 | > En mi opinión, la sintaxis es mucho mejor que otros lenguages que obligan al usuario a tipear algo como `let constant foo`. Es decir, una variable + un especificador de comportamiento. 10 | 11 | `const`es una buena práctica tanto en términos de legibilidad como de mantenibilidad y evita usar *literales mágicos*. Ejemplo: 12 | 13 | ```ts 14 | // Poca legibilidad 15 | if (x > 10) { 16 | } 17 | 18 | // Mejor! 19 | const maxRows = 10; 20 | if (x > maxRows) { 21 | } 22 | ``` 23 | 24 | #### las declaraciones const deben ser inicializadas 25 | Lo siguiente resultará en un error de compilación: 26 | 27 | ```ts 28 | const foo; // ERROR: const declarations must be initialized 29 | ``` 30 | 31 | #### El lado izquierdo de la asignación no puede ser una constante 32 | Las constantes son inmutables luego de su creación, asi que si intentas asignarles un nuevo valor obtendrás un error de compilación: 33 | 34 | ```ts 35 | const foo = 123; 36 | foo = 456; // ERROR: Left-hand side of an assignment expression cannot be a constant 37 | ``` 38 | 39 | #### Ámbito de bloque 40 | Una `const` tiene ámbito de bloque, como vimos con [`let`](./let.md): 41 | 42 | ```ts 43 | const foo = 123; 44 | if (true) { 45 | const foo = 456; // Permitido, ya que es una nueva variable limitada a este bloque `if` 46 | } 47 | ``` 48 | 49 | #### Inmutabilidad profunda 50 | Una `const` funciona objetos literales también, en lo que respecta a proteger la *referencia* de la variable: 51 | 52 | ```ts 53 | const foo = { bar: 123 }; 54 | foo = { bar: 456 }; // ERROR : Left hand side of an assignment expression cannot be a constant 55 | ``` 56 | 57 | Sin embargo, aún permite que sub-propiedades de los objetos sean mutados, como mostramos a continuación: 58 | 59 | ```ts 60 | const foo = { bar: 123 }; 61 | foo.bar = 456; // Permitido! 62 | console.log(foo); // { bar: 456 } 63 | ``` 64 | 65 | #### Preferí const 66 | 67 | Siempre usá `const`, excepto que planees inicializar una variable *lazily*, o reasignarla (usa `let` para esos casos). 68 | -------------------------------------------------------------------------------- /docs/declaration.md: -------------------------------------------------------------------------------- 1 | analogy with c headers 2 | -------------------------------------------------------------------------------- /docs/errors/common-errors.md: -------------------------------------------------------------------------------- 1 | # Errores comunes 2 | En esta sección explicaremos varios errores comunes que los usuarios experimentan en el mundo real. 3 | 4 | ## TS2304 5 | Muestras: 6 | > `Cannot find name ga` 7 | > `Cannot find name $` 8 | > `Cannot find module jquery` 9 | 10 | Probablemente esten usando una librería hecha por terceros (por ejemplo, google analytics) y no la han `declare`ado. TypeScript intenta salvarlos de cometer *errores de tipeo* y de *usar variables sin declararlas* por lo que deben ser explícitos sobre cualquier cosa que sea *una variable en tiempo de ejecución* debido a la inclusión de una librería de terceros ([más sobre cómo solucionarlo][ambient]). 11 | 12 | ## TS2307 13 | Muestras: 14 | > `Cannot find module 'underscore'` 15 | 16 | Probablemente esten usando una librería creada por terceros (por ejemplo, underscore) como un *módulo* ([más acerca de módulos][modules]) y no tienen un archivo de declaraciones ambientes para ella ([más sobre declaraciones ambiente][ambient]). 17 | 18 | ## TS1148 19 | Muestras: 20 | > `Cannot compile modules unless the '--module' flag is provided` 21 | 22 | Miren la [sección sobre módulos][modules]. 23 | 24 | ## Catch clause variable cannot have a type annotation 25 | Sample: 26 | ```js 27 | try { something(); } 28 | catch (e: Error) { // Catch clause variable cannot have a type annotation 29 | } 30 | ``` 31 | TypeScript los está protegiendo de código JavaScript que puede ser erróneo. Usen una guardia de tipos: 32 | ```js 33 | try { something(); } 34 | catch (e) { 35 | if (e instanceof Error){ 36 | // Here you go. 37 | } 38 | } 39 | ``` 40 | 41 | ## Interface `ElementClass` cannot simultaneously extend types `Component` and `Component` 42 | Esto sucede cuando tienen dos `react.d.ts` (`@types/react/index.d.ts`) en el contexto de compilacion. 43 | 44 | **Solución**: 45 | * Eliminen `node_modules` y cualquier `package-lock` (o yarn lock) y corran `npm install` de nuevo 46 | * Si no funciona, encuentren el módulo inválido (todos los módulos usados por su proyecto deberían tener un archivo `react.d.ts` como `peerDependency` y no como una `dependency` dura) y reportenlo en su proyecto. 47 | 48 | 49 | [ambient]: ../types/ambient/d.ts.md 50 | [modules]: ../project/modules.md 51 | -------------------------------------------------------------------------------- /docs/errors/main.md: -------------------------------------------------------------------------------- 1 | # Errores 2 | En esta sección discutiremos cómo leer y entender errores en TypeScript. Seguiremos este tema con ejemplos de errores comunes y sus soluciones. 3 | -------------------------------------------------------------------------------- /docs/future-javascript.md: -------------------------------------------------------------------------------- 1 | # Futuro JavaScript: Ahora 2 | Uno de los mayores beneficios de TypeScript es que te permite utilizar un número de características de ES6 y más en motores actuales (ES3 y ES5) de Javascript (como los navegadores actualres y Node.js). Aquí ahondaremos en por qué estas características son útiles y seguiremos con cómo se encuentran implementadas en TypeScript. 3 | 4 | Nota: No todas estas características están listadas para ser inmediatamente añadidas a JavaScript, pero proveen una gran utilidad en términos de organización y manutención de tu código. Además, es importante notar que sos libre de ignorar cualquier constructo que no tenga sentido en tu proyecto, aunque lo más probable es que eventualmente termines usando la mayoría ;) -------------------------------------------------------------------------------- /docs/getting-started.md: -------------------------------------------------------------------------------- 1 | * [Empezando con TypeScript](#empezando-con-typescript) 2 | * [Version de TypeScript](#version-de-typescript) 3 | 4 | # Empezando con TypeScript 5 | 6 | TypeScript compila a Javascript. Javascript es lo que vas a ejecutar realmente (sea en el navegador o en el servidor). Por lo tanto vas a necesitar lo siguiente: 7 | 8 | * Compliador para TypeScript (OSS disponible [como fuente](https://github.com/Microsoft/TypeScript/) y en [NPM](https://www.npmjs.com/package/typescript)) 9 | * Un editor de TypeScript (puedes usar un bloc de notas si quieres, pero yo use [vscode 🌹](https://code.visualstudio.com/) con una [extensión que escribí](https://marketplace.visualstudio.com/items?itemName=basarat.god). Ademas [muchos otros IDES también lo soportan]( https://github.com/Microsoft/TypeScript/wiki/TypeScript-Editor-Support)) 10 | 11 | 12 | ## Version de TypeScript 13 | 14 | En lugar de usar la version *estable* del compilador de TypeScript, vamos a estar presentando mucha información nueva en este libro que puede no estar asociada con una version numerada todavía. Generalmente, recomiendo que se utilize la version nightly, porque **el suite de tests del compilador solo atrapa mas bugs a lo largo del tiempo**. 15 | 16 | Lo puedes instalar en la línea de comando 17 | 18 | ``` 19 | npm install -g typescript@next 20 | ``` 21 | 22 | Y ahora el comando `tsc` será el ultimo y el mejor. Varios IDEs tambien lo soportan, etc. 23 | 24 | * Puedes pedirle a vscode que utilice esta versión creando `.vscode/settings.json` con el siguiente contenido: 25 | 26 | ```json 27 | { 28 | "typescript.tsdk": "./node_modules/typescript/lib" 29 | } 30 | ``` 31 | 32 | ## Obtener el Código Fuente 33 | El código para este libro se encuentra disponible en el repositorio de github https://github.com/basarat/typescript-book/tree/master/code. La mayoría de los ejemplos pueden ser copiados a vscode y puedes jugar con ellos como están. Para ejemplos que necesitan preparacion adicional (por ejemplo, módulos npm), presentaremos un link a la fuente antes de presentar el código. Por ejemplo, 34 | 35 | `este/sera/el/link/a/la/fuente.ts` 36 | ```ts 37 | // Este será el código del que hablamos 38 | ``` 39 | 40 | Con la preparación ya resulta, comenzemos con la sintaxis de TypeScript. 41 | -------------------------------------------------------------------------------- /docs/javascript/closure.md: -------------------------------------------------------------------------------- 1 | ## Cierre 2 | 3 | Lo mejor que JavaScript son los cierres. Una función en JavaScript tiene acceso a cualquier variable que haya sido definida en su ámbito externo (outer scope). Los cierres se explican mejor con ejemplos: 4 | 5 | ```ts 6 | function outerFunction(arg) { 7 | var variableInOuterFunction = arg; 8 | 9 | function bar() { 10 | console.log(variableInOuterFunction); // Acceso a una variable del ámbito externo 11 | } 12 | 13 | // Llama a la función local para demostrar que tiene acceso a arg 14 | bar(); 15 | } 16 | 17 | outerFunction("hello closure"); // imprime "hello closure!" 18 | ``` 19 | 20 | Puedes ver que la función interna tinene acceso a una variable (`variableInOuterFunction`) del ámbito externo. Las variables en el ámbito externo han sido cerradas (o rodeadas) por la función interior. De ahí el término **cierres** (o closures). El concepto en si mismo es simple y bastante intuitivo. 21 | 22 | Ahora la parte increíble: La función interna puede acceder las variables de su ámbito externo *incluso luego de que la función externa ya haya devuelto (o returned).* Esto se debe a que las variables siguen conectadas en la función interna y no dependen de la función externa. De nuevo, miremos un ejemplo: 23 | 24 | ```ts 25 | function outerFunction(arg) { 26 | var variableInOuterFunction = arg; 27 | return function() { 28 | console.log(variableInOuterFunction); 29 | } 30 | } 31 | 32 | var innerFunction = outerFunction("hello closure!"); 33 | 34 | // Noten que la función externa ha devuelto 35 | innerFunction(); // imprime "hello closure!" 36 | ``` 37 | 38 | ### Razón por la cual es genial 39 | Te permite construir objetos fácilmente, por ejemplo, revelando el patrón modelo: 40 | 41 | ```ts 42 | function createCounter() { 43 | let val = 0; 44 | return { 45 | increment() { val++ }, 46 | getVal() { return val } 47 | } 48 | } 49 | 50 | let counter = createCounter(); 51 | counter.increment(); 52 | console.log(counter.getVal()); // 1 53 | counter.increment(); 54 | console.log(counter.getVal()); // 2 55 | ``` 56 | A un nivel más alto, también es lo que permite que algo como Node.js exista (no te preocupes si no hace click en tu cerebro en este momento, lo hará eventualmente 🌹): 57 | 58 | ```ts 59 | // Pseudo código para explicar el concepto 60 | server.on(function handler(req, res) { 61 | loadData(req.id).then(function(data) { 62 | // la `res` ha sido cerrado y está disponible 63 | res.send(data); 64 | }) 65 | }); 66 | ``` 67 | -------------------------------------------------------------------------------- /docs/javascript/equality.md: -------------------------------------------------------------------------------- 1 | ## Igualdad 2 | 3 | One cosa con la que hay que tener cuidado en Javascript es la diferencia entre `==` y `===`. Como JavaScript trata de ser resiliente contra errores de programación, `==` trata de coercer los tipos de dos variables. Por ejemplo, convierte una string a un número para que los puedas comparar: 4 | 5 | ```js 6 | console.log(5 == "5"); // verdadero , TS Error 7 | console.log(5 === "5"); // falso , TS Error 8 | ``` 9 | 10 | Sin embargo, las elecciones de Javascript no siempre son ideales. Por ejemplo, en el ejemplo que sigue la primera declaración es falsa porque `""` y `"0"` son los dos strings y claramente no iguales. Sin embargo, en el segundo caso, ambos `0` y la string vacía (`""`) son falsy (en otras palabras, se comportan como `falso`) y son, por lo tanto, iguales en lo que respecta a `==`. Ambas declaraciones son falsas cuando se utiliza `===`. 11 | 12 | ```js 13 | console.log("" == "0"); // falso 14 | console.log(0 == ""); // verdadero 15 | 16 | console.log("" === "0"); // falso 17 | console.log(0 === ""); // falso 18 | ``` 19 | 20 | > Notemos que tanto `string == numbero` como `string === numbero` son errores de compilación en TypeScript, asi que normalmente no tienes que preocuparte por esto. 21 | 22 | De forma similar a `==` vs. `===`, hay un `!=` vs. `!==` 23 | 24 | Así que un consejo Pro: siempre usá `===` y `!==` excepto para checkear nulls (cubriremos por qué luego). 25 | Similar to `==` vs. `===`, there is `!=` vs. `!==` 26 | 27 | ## Igualdad estructural 28 | Si quieres comparar dos objectos para igualdad estructural, `==`/`===` ***no*** son suficientes. Por ejemplo, 29 | 30 | ```js 31 | console.log({a:123} == {a:123}); // Falso 32 | console.log({a:123} === {a:123}); // Falso 33 | ``` 34 | Para hacer este tipo de chequeos debes usar el paquete de npm [deep-equal](https://www.npmjs.com/package/deep-equal). Por ejemplo: 35 | 36 | ```js 37 | import * as deepEqual from "deep-equal"; 38 | 39 | console.log(deepEqual({a:123},{a:123})); // Verdadero 40 | ``` 41 | 42 | Sin embargo, generalmente no es necesario realizar chequeos profundos y todo lo que realmente es necesario es chequear por medio de un `id`. Por ejemplo: 43 | 44 | ```ts 45 | type IdDisplay = { 46 | id: string, 47 | display: string 48 | } 49 | const list: IdDisplay[] = [ 50 | { 51 | id: 'foo', 52 | display: 'Foo Select' 53 | }, 54 | { 55 | id: 'bar', 56 | display: 'Bar Select' 57 | }, 58 | ] 59 | 60 | const fooIndex = list.map(i => i.id).indexOf('foo'); 61 | console.log(fooIndex); // 0 62 | ``` 63 | -------------------------------------------------------------------------------- /docs/javascript/recap.md: -------------------------------------------------------------------------------- 1 | # Tu JavaScript es TypeScript 2 | 3 | Hubieron (y van a seguir habiendo) muchos competidores en compiladores de *alguna sintaxis* a *JavaScript*. TypeScript es diferente en el sentido de que *Tu Javascript es Typescript*. Aquí hay un diagrama: 4 | 5 | ![JavaScript es TypeScript](https://raw.githubusercontent.com/basarat/typescript-book/master/images/venn.png) 6 | 7 | Sin embargo, eso significa que *tenés que aprender JavaScript* (las buenas noticias son que *vos **solo** tenes que aprender JavaScript*). TypeScript simplemente está estandarizando todas las maneras en las que poder proveer *buena documentación* en JavaScript. 8 | 9 | * Darte una nueva sintaxis no ayuda a resolver las bugs (mirandote a vos CoffeScript) 10 | * Crear un nuevo lenguaje te abstrae demasiado de tus tiempos de ejecucion, comunidades (mirandote a vos Dart) 11 | 12 | Typescript es Javascript con documentación. 13 | 14 | ## Mejorando JavaScript 15 | 16 | TypeScript tratará de protegerte de partes de JavaScript que nunca funcionaron (así que no tenés que recordar estas cosas): 17 | 18 | ```ts 19 | [] + []; // JavaScript te dará "" (lo que no tiene sentido), TypeScript tirará un error 20 | 21 | // 22 | // otras cosas que no tienen sentido en Javascript 23 | // - no hay errores en tiempo de ejecución (hace que depurar sea dificil) 24 | // - pero TypeScript te dará errores al compilar (haciendo la depuración innecesaria) 25 | // 26 | {} + []; // JS : 0, TS Error 27 | [] + {}; // JS : "[object Object]", TS Error 28 | {} + {}; // JS : NaN or [object Object][object Object] dependiendo del navegador, TS Error 29 | "hello" - 1; // JS : NaN, TS Error 30 | 31 | function add(a,b) { 32 | return 33 | a + b; // JS : undefined, TS Error 'unreachable code detected' (código inacalcanzable detectado) 34 | } 35 | ``` 36 | Esencialmente TypeScript está *linteando* Javascript. Pero haciendo un mejor trabajo que otros linters que no tienen *información sobre tipos* 37 | 38 | ## Igual tenés que aprender JavaScript 39 | 40 | Habiendo dicho eso, TypeScript es muy pragmatico sobre le hecho de que *estás escribiendo JavaScript*, por lo que hay ciertas cosas sobre JavaSCript que igual debes saber en order para no caer desprevenido. Discutamolas a continuación. 41 | 42 | > Nota: TypeScript es un superconjunto de Javascript. Pero con documentación que puede ser utilizada por compiladores / IDEs ;) 43 | -------------------------------------------------------------------------------- /docs/javascript/references.md: -------------------------------------------------------------------------------- 1 | ## Referencias 2 | 3 | Más allá de los literales, cualquier Objeto en JavaScript (incluyendo funciones, arrays, regexp, etc) son referencias. Esto significa lo siguiente: 4 | 5 | ### Las mutaciones ocurren en todas las referencias 6 | 7 | ```js 8 | var foo = {}; 9 | var bar = foo; // bar es una referencia al mismo objeto 10 | 11 | foo.baz = 123; 12 | console.log(bar.baz); // 123 13 | ``` 14 | 15 | ### La igualdad corresponde a las referencias 16 | 17 | ```js 18 | var foo = {}; 19 | var bar = foo; // bar es una referencia 20 | var baz = {}; // baz es un *nuevo objecto* diferente a `foo` 21 | 22 | console.log(foo === bar); // verdadero 23 | console.log(foo === baz); // falso 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/javascript/this.md: -------------------------------------------------------------------------------- 1 | ## this 2 | 3 | Cualquier acceso a la palabra clave `this` dentro de una función está en realidad controlado por como la función es llamada, a lo que habitualmente se le llama "contexto de llamada" '(o *calling context*) 4 | 5 | Aquí hay un ejemplo: 6 | 7 | ```ts 8 | function foo() { 9 | console.log(this); 10 | } 11 | 12 | foo(); // anota lo global, por ejemplo `window` en los navegadores 13 | let bar = { 14 | foo 15 | } 16 | bar.foo(); // anota `bar` ya que `foo` Logs out `bar` as `foo` was called on `bar` 17 | ``` 18 | Así que ten cuidado con tu utilización de `this`. Si quieres desconectar `this` en una clase del contexto de llamada, utiliza una función de flecha. [más sobre eso luego][arrow] 19 | 20 | [arrow]:../arrow-functions.md 21 | -------------------------------------------------------------------------------- /docs/javascript/truthy.md: -------------------------------------------------------------------------------- 1 | ## Truthy 2 | 3 | JavaScript tiene un concepto `truthy`, es decir, cosas que son evaluadas como `verdaderas` en ciertas situaciones (por ejemplo, en condiciones `if` y los operadores booleanos `&&` y `||`). Las siguientes cosas son truthy en JavaScript. Por ejemplo, cualquier número excepto `0` es evaluado como truthy: 4 | 5 | ```ts 6 | if (123) { // será tratado como `true` 7 | console.log('Cualquier número que no sea 0 es truthy'); 8 | } 9 | ``` 10 | 11 | Algo que no es truthy es `falsy`. 12 | 13 | Aquí hay una tabla de referencia. 14 | 15 | 16 | | Tipo de variable | Cuándo es *falsy* | Cuándo es *truthy* | 17 | |--------------------|--------------------------|--------------------------| 18 | | `boolean` | `false` | `true` | 19 | | `string` | `''` (string vacía) | cualquier otra string | 20 | | `number` | `0` `NaN` | cualquier otro número | 21 | | `null` | siempre | nunca | 22 | | `undefined` | siempre | nunca | 23 | | Cualquier Objeto incluyendo los vacíos (`{}`, `[]`) | nunca | siempre | 24 | 25 | 26 | ### Siendo explícito 27 | 28 | > El patrón `!!` 29 | 30 | Comúnmente ayuda ser explícito en la intención de tratar un valor como `boolean` y convertirlo en un *verdadero booleano* (`true`|`false`). Puedes convertir valores a verdaderos booleanos al prefixarlos con `!!`, por ejemplo, `!!foo`. Es sólo `!` utilizado dos veces. El primer `!` convierte la variable (en este caso `foo`) a un booleano, pero invierte la lógica <*truthy* - `!` > `false`, *falsy* - `!` > `true`. El segundo vuelve a invertirlo para igualar la naturaleza del objeto original: *truthy* -`!`> `false` -`!`> `true`. 31 | 32 | Es común utilizar este patrón en muchos lugares. Por ejemplo, 33 | 34 | ```js 35 | // variables directas 36 | const hasName = !!name; 37 | 38 | // Como miembros de objetos 39 | const someObj = { 40 | hasName: !!name 41 | } 42 | 43 | // e.g. en ReactJS JSX 44 | {!!someName &&
{someName}
} 45 | ``` 46 | -------------------------------------------------------------------------------- /docs/jsx/others.md: -------------------------------------------------------------------------------- 1 | # JSX por fuera de React 2 | 3 | TypeScript les permitirá utilizar algo más que React con JSX preservando la seguridad de tipos. La sigueinte lista muestra los items customizables, pero noten que esto es para autores de frameworks UI avanzados: 4 | 5 | * Pueden inhabilitar la emisión de estilo `react` usando la opción `"jsx": "preserve"`. Esto significa que JSX es emitido *como está* y que luego podrán usar su propio transpilador para las porciones con JSX. 6 | * Usando el módulo global `JSX`: 7 | * Podrán controlar que etiquetas HTML se encuentran disponibles y cómo son controlados los tipos mediante la customización de los miembros de la interfaz `JSX.IntrisicElements`. 8 | * Al usar componentes: 9 | * Pueden controlar cuál `clase` puede ser heredada por componentes mediante la customización de la declaración default `interface ElementClass extends React.Component { }`. 10 | * Pueden controlar qué propiedad es usanda para controlar los tipos de los atributos (el default es `props`) customizando la declaración `declare module JSX { interface ElementAttributesProperty { props: {}; } }`. 11 | 12 | ## `jsxFactory` 13 | 14 | Pasar `--jsxFactory ` junto con `--jsx react` permite que se use una fábrica JSX diferente `React`. 15 | 16 | El nuevo nombre de la fábrica será usado para llamar las funciones `createElement`. 17 | 18 | ### Ejemplo 19 | 20 | ```ts 21 | import {jsxFactory} from "jsxFactory"; 22 | 23 | var div =
Hello JSX!
24 | ``` 25 | 26 | Compilado con: 27 | 28 | ```shell 29 | tsc --jsx react --reactNamespace jsxFactory --m commonJS 30 | ``` 31 | 32 | Resulta: 33 | 34 | ```js 35 | "use strict"; 36 | var jsxFactory_1 = require("jsxFactory"); 37 | var div = jsxFactory_1.jsxFactory.createElement("div", null, "Hello JSX!"); 38 | ``` 39 | 40 | ## `jsx` pragma 41 | 42 | Hasta pueden especificar una `jsxFactory` diferente por archivo, usando `jsxPragma`: 43 | 44 | 45 | ```js 46 | /** @jsx jsxFactory */ 47 | import {jsxFactory} from "jsxFactory"; 48 | 49 | var div =
Hola JSX!
50 | ``` 51 | 52 | Con `--jsx react` este archivo emitirá para usar la fábrica declarada en el jsx pragma: 53 | ```js 54 | "use strict"; 55 | var jsxFactory_1 = require("jsxFactory"); 56 | var div = jsxFactory_1.jsxFactory.createElement("div", null, "Hello JSX!"); 57 | ``` 58 | -------------------------------------------------------------------------------- /docs/jsx/tsx.md: -------------------------------------------------------------------------------- 1 | # Soport JSX 2 | 3 | TypeScript soporta la transpilación y el análisis de código JSX. Si JSX no les es familiar, aquí hay un extracto de la [web oficial](https://facebook.github.io/jsx/): 4 | 5 | > JSX es una extensión de sintaxis similar a XML para ECMAScript sin ninguna semántica definida. NO es la intención que sea utilizada por motores o navegadores. NO es una propuesta de incorporar JSX a las especificaciones de ECMAScript en sí mismas. La intención es que sea usado por varios preprocesadores (transpiladores) para tranformar estos tokens en ECMAScript estándar. 6 | 7 | Los motivos detrás de la creación de JSX es permitir que los usuarios escriban vistas similares a HTML *en JavaScript*, lo que les permitirá: 8 | 9 | * Tener la vista con control de Tipos por el mismo código que controlará su JavaScript 10 | * Que la vista esté al tanto del contexto en el que va a operar (para, por ejemplo, fortalecer la conexión *controler-vista* en MVC tradicional) 11 | * Reusar patrones de JavaScript para mantener HTML, como `Array.prototype.map`, `?:`, `switch`, etc, en lugar de crear alternativas nuevas (y probablemente mal tipadas) 12 | 13 | Esto disminuye las chances de errores e incrementa la mantenibilidad de tus interfaces de usuarios. El consumidor principal de JSX en este momento ens [ReactJS de Facebook(http://facebook.github.io/react/). Este será el uso de JSX que discutiremos en este libro. 14 | -------------------------------------------------------------------------------- /docs/options/intro.md: -------------------------------------------------------------------------------- 1 | # Conveniencia vs solidez 2 | 3 | Hay alguans cosas que TypeScript previene que hagan, como usar una variable que *no fue declarada nunca* (por supuesto que pueden usar un *archivo de declaraciones* para sistemas externos). 4 | 5 | Habiendo dicho eso, tradicionalmente los lenguajes de programación tienen un límite duro entre lo que es y no es permitido en el sistema de tipos. TypeScript es diferente ya que les da el control de dónde dibujar esa línea. Esto ocurre para permitirles usar el JavaScript que conocen y aman con el nivel de seguridad que **ustedes** quieran. Hay muchas opciones de compilador para controlar este límite, así que miremoslo en más detalle: 6 | 7 | ## Opciones booleanas 8 | 9 | Las `compilerOptions` que son `boolean` pueden ser especificadas como `compilerOptions` en `tsconfig.json`: 10 | 11 | ```json 12 | { 13 | "compilerOptions": { 14 | "someBooleanOption": true 15 | } 16 | } 17 | ``` 18 | 19 | o en la línea de comandos 20 | 21 | ```sh 22 | tsc --someBooleanOption 23 | ``` 24 | 25 | > Todas estas son `false` por default. 26 | 27 | Hagan click [aquí](https://www.typescriptlang.org/docs/handbook/compiler-options.html) para ver una lista de todas las opcioens del compilador. 28 | -------------------------------------------------------------------------------- /docs/options/noImplicitAny.md: -------------------------------------------------------------------------------- 1 | # noImplicitAny 2 | 3 | Hay algunas cosas que no pueden ser inferidas o para las que inferirlas podría resultar en errores inesperados. Un buen ejemplo son los argumentos de una función. Si no los anotan, es poco claro qué deberían hacer y qué debería ser inválido. Por ejemplo: 4 | 5 | ```ts 6 | function log(someArg) { 7 | sendDataToServer(someArg); 8 | } 9 | 10 | // Cuál argumento es válido y cuál no? 11 | log(123); 12 | log('hello world'); 13 | ``` 14 | 15 | Por este motivo, si ustedes no anotan los tipos de los argumentos de una función, TypeScript asume `any` y continúa. En la práctica, esto es lo mismo que apagar el sistema de control de tipos para estos casos, que es lo que querría un desarrollador JavaScript. Pero puede agarrar desprevenidas a las personas que quieren una alta seguridad de tipos. Por eso existe la opción `noImplicitAny`, que al ser encendida alertará sobre los casos en los que los tipos no pueden ser inferidos: 16 | 17 | ```ts 18 | function log(someArg) { // Error : someArg has an implicit `any` type 19 | sendDataToServer(someArg); 20 | } 21 | ``` 22 | 23 | Claro que igual pueden proceder a anotarlo: 24 | 25 | ```ts 26 | function log(someArg: number) { 27 | sendDataToServer(someArg); 28 | } 29 | ``` 30 | 31 | Y si realmente quieren *cero seguridad* pueden marcarlo *explícitamente* como `any`: 32 | 33 | ```ts 34 | function log(someArg: any) { 35 | sendDataToServer(someArg); 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/project/compilation-context.md: -------------------------------------------------------------------------------- 1 | ## Contexto de compilación 2 | 3 | El contexto de compilación es, básicamente, un término elaborado para agrupar los archivos que TypeScript va a analizar para determinar qué es válido y qué no. Junto con la información sobre qué archivos leer, el contexto de compilación contiene información acerca de *qué opciones de compilación* se encuentran utilizadas. Una gran manera de definir esta agrupación lógica (también nos gusta usar el término *proyecto*) es mediante la creación del archivo `tsconfig.js`. 4 | -------------------------------------------------------------------------------- /docs/project/declarationspaces.md: -------------------------------------------------------------------------------- 1 | ## Espacios de declaración 2 | 3 | Hay dos tipos de espacios de declaración en TypeScript: el espacio de declaración de *variables* y el espacio de declaración de *tipo*. Estos conceptos son explorados en detalle a continuación. 4 | 5 | ### Espacio de declaración de Tipo 6 | El espacio de declaración de tipos contiene cosas que pueden ser usadas como anotación de tipos. Por ejemplo, las siguientes son algunas declaraciones de tipos: 7 | 8 | ```ts 9 | class Foo {}; 10 | interface Bar {}; 11 | type Bas = {}; 12 | ``` 13 | Esto significa que peudes usar `Foo`, `Bar`, `Bas`, etc como anotaciones de tipo: 14 | 15 | ```ts 16 | var foo: Foo; 17 | var bar: Bar; 18 | var bas: Bas; 19 | ``` 20 | 21 | Notemos que aunque tienes la `interface Bar`, *no la puedes usar como una variable* porque no contribuye al *espacio de declaración de variables*. Mostramos esto a continuación: 22 | 23 | ```ts 24 | interface Bar {}; 25 | var bar = Bar; // ERROR: "cannot find name 'Bar'" 26 | ``` 27 | 28 | La razón por la que dice `cannot find name` ("no es posible enconrar el nombre") es porque el nombre `Bar` *no está definido* en el espacio de declaración de *variables*. Esto nos trae al siguiente tema: "Espacio de declaración de variables" 29 | 30 | ### Espacio de declaración de variables 31 | El espacio de declaración de variables contiene cosas que puedes usar como variables. Vimos que tener `class Foo` contribuye un tipo `Foo` al espacio de declaración de *tipos*. Adivina qué? También contribuye una *variable* `Foo` al espacio de declaración de *variables*, como mostramos a continuación: 32 | 33 | ```ts 34 | class Foo {}; 35 | var someVar = Foo; 36 | var someOtherVar = 123; 37 | ``` 38 | Esto es bárbaro, ya que a veces quieres pasar clases como si fuesen variables. Recuerda que: 39 | 40 | * No pudimos usar algo como una `interface` que se encuentra *únicamente* en el espacio de declaración de *tipos* como una variable. 41 | 42 | Similarmente, algo que declares con `var`, se encuentra *únicamente* en el espacio de declaración de *variables* y no puede ser usado como anotación de tipo: 43 | 44 | ```ts 45 | var foo = 123; 46 | var bar: foo; // ERROR: "cannot find name 'foo'" 47 | ``` 48 | a razón por la que dice `cannot find name` ("no es posible enconrar el nombre") es porque el nombre `foo` *no está definido* en el espacio de declaración de *tipos*. 49 | -------------------------------------------------------------------------------- /docs/project/files.md: -------------------------------------------------------------------------------- 1 | ## Cuáles archivos? 2 | 3 | Usamos `include` y `exclude` para especificar archivos / carpetas / globs. Por ejemplo: 4 | 5 | 6 | ```json 7 | { 8 | "include":[ 9 | "./folder" 10 | ], 11 | "exclude":[ 12 | "./folder/**/*.spec.ts", 13 | "./folder/someSubFolder" 14 | ] 15 | } 16 | ``` 17 | 18 | ### Globs 19 | 20 | * Para globs: `/**/*` (por ejemplo, `unacarpeta/**/*`) significa todas las carpetas y archivos (las extensiones `.ts`/`.tsx` serán incluidas automáticamente, y si `allowJs:true`, también lo serán las extensiones `.js`/`.jsx`). 21 | 22 | ### Opción `files` 23 | Puedes usar `files` para ser explícito: 24 | 25 | ```json 26 | { 27 | "files":[ 28 | "./some/file.ts" 29 | ] 30 | } 31 | ``` 32 | 33 | Pero no se recomienda ya que vas a tener que mantenerlo al día. En su lugar, usa `include` para incluir la carpeta contenedora. 34 | -------------------------------------------------------------------------------- /docs/project/globals.md: -------------------------------------------------------------------------------- 1 | # globals.d.ts 2 | 3 | Discutimos módulos *globales* y en *archivos* cuadno cubrimos [proyectos](./modules.md) y recomendamos usando los módulos basados en archivo para evitar contaminar el namespace global. 4 | 5 | Sin embargo, si tienen desarrolladores TypeScript que recién estan comenzando, pueden darles un archivo `globals.d.ts` donde poner interfaces y tipos en el namespeace global, y así facilitarles el acceso a algunos *tipos* al tenerlos *mágicamente* disponibles en *toda* la base de código de TypeScript. 6 | 7 | > Para cualquier código que vaya a generar *JavaScript*, es altamente recomendable usar los *módulos en archivos*. 8 | 9 | * `globals.d.ts` es útil para agregar extensiones a `lib.d.ts` en caso de que lo necesiten 10 | * También sirve para `declare module "some-library-you-dont-care-to-get-defs-for";` rápidamente cuando estén migrando JS a TS. 11 | -------------------------------------------------------------------------------- /docs/project/modules.md: -------------------------------------------------------------------------------- 1 | ## Módulos 2 | 3 | ### Módulo Global 4 | 5 | Por default, cuando comenzas a tipear código en un archivo de TypeScript, tu código se encuentra en un espacio de nombre (*namespace*) global. A modo de demostración, consideremos el archivo `foo.ts`: 6 | 7 | ```ts 8 | var foo = 123; 9 | ``` 10 | 11 | Si ahora creases un *nuevo* archivo `bar.ts` en el mismo proyecto, el sistema de tipos de TypeScript te *permitiría* usar la variable `foo` como si estuviese disponible globalmente: 12 | 13 | ```ts 14 | var bar = foo; // permitido 15 | ``` 16 | No es necesario decir que tener un namespace global es peligroso, ya que abre la posibilidad de conflictos de nombramiento en tu código. Recomendamos utilizar módulos en su lugar, los cuales presentaremos a continuación. 17 | 18 | ### Módulo como archivo 19 | También llamados *módulos externos*. Si tienes un `import` o un `export` en el nivel raíz de un archivo TypeScript, entonces este crea un ámbito *local* dentro de ese archivo. Por lo tanto, si fueramos a cambiar el archivo `foo.ts` de la siguiente manera (prestá atención a la utilización de `export`): 20 | 21 | ```ts 22 | export var foo = 123; 23 | ``` 24 | 25 | ya no tendriamos a `foo` en el namespace global. Esto puede ser demostrado creado un nuevo archivo `bar.ts` de la siguiente manera: 26 | 27 | ```ts 28 | var bar = foo; // ERROR: "cannot find name 'foo'" 29 | ``` 30 | 31 | Si quieres usar cosas de `foo.ts` en `bar.ts` *neceistas importarlas explícitamente*. A continuación mostramos un `bar.ts` actualizado: 32 | 33 | ```ts 34 | import { foo } from "./foo"; 35 | var bar = foo; // Permitido 36 | ``` 37 | Usar `import` en `bar.ts` no solo te permite traer cosas de otros archivos, sino que también marca el archivo `bar.ts` como un *módulo* y, por lo tanto, cualquier declaración hecha en `bar.ts` tampoco contamina el namespace global. 38 | 39 | El tipo de código JavaScript que es generado a partir de un archivo TypeScript que utiliza módulos externos es "decidido" por la flag de compilación `module`. 40 | -------------------------------------------------------------------------------- /docs/project/namespaces.md: -------------------------------------------------------------------------------- 1 | ## Namespaces 2 | Namespaces (espacios de nombre) nos proveen con una sintaxis conveniente respecto de un patrón comúnmente usado en JavaScript: 3 | 4 | ```ts 5 | (function(something) { 6 | 7 | something.foo = 123; 8 | 9 | })(something || (something = {})) 10 | ``` 11 | 12 | Básicamente `something || (something = {})` permite a la función anónima `function(something) {}` *agregar cosas a un objeto existente* (la porción `something ||`) o *crear un nuevo objeto y luego agregar cosas a ese objeto* (la porción `|| (something = {})`). Esto significa que peudes tener dos bloques 13 | Basically `something || (something = {})` allows an anonymous function `function(something) {}` to *add stuff to an existing object* (the `something ||` portion) or *start a new object then add stuff to that object* (the `|| (something = {})` portion). Esto significa que puede tener dos bloques de este tipo divididos por algún límite de ejecución: 14 | 15 | ```ts 16 | (function(something) { 17 | 18 | something.foo = 123; 19 | 20 | })(something || (something = {})) 21 | 22 | console.log(something); // {foo:123} 23 | 24 | (function(something) { 25 | 26 | something.bar = 456; 27 | 28 | })(something || (something = {})) 29 | 30 | console.log(something); // {foo:123, bar:456} 31 | 32 | ``` 33 | 34 | Esto se usa comúnmente en el mundo JavaScript para asegurarnos de que nada se derrame hacia el namespace global. Con módulos basados en archivos, no hace falta preocuparse por esto, pero el patrón sigue siendo útil para *agrupaciones locales* de una serie de funciones. Por esto, TypeScrip provee la palabra clave `namespace` para agruparlos. Por ejemplo: 35 | 36 | ```ts 37 | namespace Utility { 38 | export function log(msg) { 39 | console.log(msg); 40 | } 41 | export function error(msg) { 42 | console.error(msg); 43 | } 44 | } 45 | 46 | // usage 47 | Utility.log('Call me'); 48 | Utility.error('maybe!'); 49 | ``` 50 | 51 | La palabra clave `namespace` genera el mismo JavaScript que vimos previamente: 52 | 53 | ```ts 54 | (function (Utility) { 55 | 56 | // Add stuff to Utility 57 | 58 | })(Utility || (Utility = {})); 59 | ``` 60 | Algo importante de remarcar es que los namespaces pueden estar anidades por lo que peudes hacer cosas como `namespace Utility.Messaging` para anidar un namespace `Messaging` bajo `Utility`. 61 | 62 | Para la mayoría de los proyectos recomendamos usar módulos externos y usar `namespace` para demos rápidas y para portar código Javascript viejo. 63 | -------------------------------------------------------------------------------- /docs/project/project.md: -------------------------------------------------------------------------------- 1 | # Proyecto 2 | 3 | Para crear un proyecto existoso usando TypeScript, debes entender las variadas formas de lenguage disponibles para organización de proyectos. En esta sección, cubriremos el "contexto de compilación", los espacios de declaración y los módulos. 4 | -------------------------------------------------------------------------------- /docs/rest-parameters.md: -------------------------------------------------------------------------------- 1 | ### Parámetros Rest 2 | Los parámetros rest (denotados por `...NombreDelUltimoArgumento` ) permiten aceptar múltiples argumentos en una función y obtenerlos como un array. Esto se demuestra en el ejemplo a continuación. 3 | 4 | ```ts 5 | function iTakeItAll(first, second, ...allOthers) { 6 | console.log(allOthers); 7 | } 8 | iTakeItAll('foo', 'bar'); // [] 9 | iTakeItAll('foo', 'bar', 'bas', 'qux'); // ['bas','qux'] 10 | ``` 11 | 12 | Los parámetros rest pueden ser utilizados en cualquier función ya sea `function`/`()=>`/`class member`. 13 | -------------------------------------------------------------------------------- /docs/staging/async-await.md: -------------------------------------------------------------------------------- 1 | ### Async - Await 2 | -------------------------------------------------------------------------------- /docs/staging/generators.md: -------------------------------------------------------------------------------- 1 | ### Generators 2 | Also called `function *`, generators allow you to create functions whose execution can be paused and then later resumed maintaining the state between pause-resume transitions. The value returned from a generator is called an `iterator` and can be used to control this `pause-resume` transition. 3 | 4 | Here is a simple example of a generator function that generates an *infinite* list of whole numbers. 5 | 6 | ```ts 7 | function* wholeNumbers() { 8 | var current = 0; 9 | while(true) { 10 | yield current++; 11 | } 12 | } 13 | ``` 14 | 15 | The `yield` contextual keyword is used to return control from a generator (effectively pausing function execution) along with an optional value (here `current`). You can get access to this value using the `iterator`'s `.next()` member function, this is shown below: 16 | 17 | ```ts 18 | function* wholeNumbers() { 19 | var current = 0; 20 | while(true) { 21 | yield current++; 22 | } 23 | } 24 | var iterator = wholeNumbers(); 25 | console.log(iterator.next()); // 0 26 | console.log(iterator.next()); // 1 27 | console.log(iterator.next()); // 2 28 | // so on till infinity.... 29 | ``` 30 | 31 | Now that you have seen `function*`, `yield` and `.next()` we can dig deeper. 32 | 33 | #### Catching Errors 34 | Any errors thrown (intentially using `throw` or unintentionally due to error) from the generator can be caught using `try/catch` just like normal function executions. This is demonstrated below: 35 | 36 | ```ts 37 | function* wholeNumbers() { 38 | var current = 0; 39 | while(true) { 40 | if (current === 3) 41 | throw new Error('3 is the magic number'); 42 | else 43 | yield current++; 44 | } 45 | } 46 | var iterator = wholeNumbers(); 47 | console.log(iterator.next()); // 0 48 | console.log(iterator.next()); // 1 49 | console.log(iterator.next()); // 2 50 | try { 51 | console.log(iterator.next()); // Will throw an error 52 | } 53 | catch(ex) { 54 | console.log(ex.message); // 3 is the magic number 55 | } 56 | ``` 57 | 58 | #### Controlling function execution externally 59 | The iterator returned from the generator function can be used to control the state *inside* the generator function as well. 60 | 61 | // TODO: example 62 | -------------------------------------------------------------------------------- /docs/state/mobx.md: -------------------------------------------------------------------------------- 1 | ## MobX 2 | 3 | > [PRO Egghead course on MobX TypeScript React](https://egghead.io/courses/develop-react-applications-with-mobx-and-typescript) 4 | 5 | -------------------------------------------------------------------------------- /docs/styleguide/sample.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var formatting; 3 | (function (formatting) { 4 | var FooVar; 5 | function BarFunc() { } 6 | })(formatting || (formatting = {})); 7 | var asdfasdf; 8 | (function (asdfasdf) { 9 | var Foo = (function () { 10 | function Foo() { 11 | } 12 | Foo.prototype.baz = function () { }; 13 | return Foo; 14 | }()); 15 | })(asdfasdf || (asdfasdf = {})); 16 | -------------------------------------------------------------------------------- /docs/styleguide/sample.ts: -------------------------------------------------------------------------------- 1 | export var test; 2 | 3 | namespace formatting { 4 | var FooVar; 5 | function BarFunc() { } 6 | } 7 | 8 | namespace asdfasdf { 9 | class Foo { 10 | bar: number; 11 | baz() { } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /docs/styleguide/tsconfig.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /docs/testing/intro.md: -------------------------------------------------------------------------------- 1 | # Pruebas 2 | TypeScript puede ser usado con cualquier framework de pruebas (testeo) que quieran. En el peor de los casos, siempre pueden hacer una simple transformación `TypeScript -> JavaScript` y seguir felices su camino. 3 | 4 | Habiendo dicho eso, en esta sección consideraremos ciertas opciones que hemos disfrutado ampliamente 🌹 5 | -------------------------------------------------------------------------------- /docs/tips/barrel.md: -------------------------------------------------------------------------------- 1 | ## Barrel 2 | 3 | A barrel is a way to rollup exports from several modules into a single convenient module. The barrel itself is a module file that re-exports selected exports of other modules. 4 | 5 | Imagine the following class structure in a library: 6 | 7 | ```ts 8 | // demo/foo.ts 9 | export class Foo {} 10 | 11 | // demo/bar.ts 12 | export class Bar {} 13 | 14 | // demo/baz.ts 15 | export class Baz {} 16 | ``` 17 | 18 | Without a barrel, a consumer would need three import statements: 19 | 20 | ```ts 21 | import { Foo } from '../demo/foo'; 22 | import { Bar } from '../demo/bar'; 23 | import { Baz } from '../demo/baz'; 24 | ``` 25 | 26 | You can instead add a barrel `demo/index.ts` containing the following: 27 | 28 | ```ts 29 | // demo/index.ts 30 | export * from './foo'; // re-export all of its exports 31 | export * from './bar'; // re-export all of its exports 32 | export * from './baz'; // re-export all of its exports 33 | ``` 34 | 35 | Now the consumer can import what it needs from the barrel: 36 | 37 | ```ts 38 | import { Foo, Bar, Baz } from '../demo'; // demo/index.ts is implied 39 | ``` 40 | 41 | ### Named exports 42 | Instead of exporting `*`, you can choose to export the module in a name. E.g., assume that `baz.ts` has functions: 43 | 44 | ```ts 45 | // demo/foo.ts 46 | export class Foo {} 47 | 48 | // demo/bar.ts 49 | export class Bar {} 50 | 51 | // demo/baz.ts 52 | export function getBaz() {} 53 | export function setBaz() {} 54 | ``` 55 | 56 | If you would rather not export `getBaz` / `setBaz` from demo you can instead put them in a variable by importing them in a name and exporting that name as shown below: 57 | 58 | ```ts 59 | // demo/index.ts 60 | export * from './foo'; // re-export all of its exports 61 | export * from './bar'; // re-export all of its exports 62 | 63 | import * as baz from './baz'; // import as a name 64 | export { baz }; // export the name 65 | ``` 66 | 67 | And now the consumer would look like: 68 | 69 | ```ts 70 | import { Foo, Bar, baz } from '../demo'; // demo/index.ts is implied 71 | 72 | // usage 73 | baz.getBaz(); 74 | baz.setBaz(); 75 | // etc. ... 76 | ``` 77 | -------------------------------------------------------------------------------- /docs/tips/build-toggles.md: -------------------------------------------------------------------------------- 1 | ## Build Toggles 2 | 3 | It is common to switch in JavaScript projects based on where they are being run. You can do this quite easily with webpack as it supports *dead code elimination* based on environment variables. 4 | 5 | Add different targets in your `package.json` `scripts`: 6 | 7 | ```json 8 | "build:test": "webpack -p --config ./src/webpack.config.js", 9 | "build:prod": "webpack -p --define process.env.NODE_ENV='\"production\"' --config ./src/webpack.config.js", 10 | ``` 11 | 12 | Of course I am assuming you have `npm install webpack --save-dev`. Now you can run `npm run build:test` etc. 13 | 14 | Using this variable is super easy as well: 15 | 16 | ```ts 17 | /** 18 | * This interface makes sure we don't miss adding a property to both `prod` and `test` 19 | */ 20 | interface Config { 21 | someItem: string; 22 | } 23 | 24 | /** 25 | * We only export a single thing. The config. 26 | */ 27 | export let config: Config; 28 | 29 | /** 30 | * `process.env.NODE_ENV` definition is driven from webpack 31 | * 32 | * The whole `else` block will be removed in the emitted JavaScript 33 | * for a production build 34 | */ 35 | if (process.env.NODE_ENV === 'production') { 36 | config = { 37 | someItem: 'prod' 38 | } 39 | console.log('Running in prod'); 40 | } else { 41 | config = { 42 | someItem: 'test' 43 | } 44 | console.log('Running in test'); 45 | } 46 | ``` 47 | 48 | > We use `process.env.NODE_ENV` just because it is conventional in a lot of JavaScript libraries themselves e.g. `React`. 49 | -------------------------------------------------------------------------------- /docs/tips/classesAreUseful.md: -------------------------------------------------------------------------------- 1 | ## Las clases son útiles 2 | 3 | Es muy común tener la siguiente estructura: 4 | 5 | ```ts 6 | function foo() { 7 | let someProperty; 8 | 9 | // Más código de inicialización 10 | 11 | function someMethod() { 12 | // hace algo con `someProperty` 13 | // Y potencialmente otras cosas 14 | } 15 | // Tal vez otros métodos 16 | 17 | return { 18 | someMethod, 19 | // Tal vez otros métodos 20 | }; 21 | } 22 | ``` 23 | Este patrón se llama *patrón de revelación de módulos* y es bastante común en JavaScript (aprovecha los cierres de JavaScript). 24 | 25 | Si usan [*módulos en archivos* (lo que deberían hacer ya que el ámbito global es malo)](../project/modules.md) entonces *su archivo es el mismo*. Sin embargo, hay muchos casos en los que programadores escribirán código de la siguiente manera: 26 | 27 | ```ts 28 | let someProperty; 29 | 30 | function foo() { 31 | // Código de inicialización 32 | } 33 | foo(); // Código de inicialización 34 | 35 | someProperty = 123; // Algo más de inicialización 36 | 37 | // Una función de utilidad no exportada 38 | 39 | // luego 40 | export function someMethod() { 41 | 42 | } 43 | ``` 44 | 45 | A pesar de que no somos grandes fans de la herencia *encuentramos que dejar que la gente use clases los ayuda a organizar su código mejor*. El mismo desarrollador hubiese escrito lo siguiente intuitivamente: 46 | 47 | ```ts 48 | class Foo { 49 | public someProperty; 50 | 51 | constructor() { 52 | // Código de inicialización 53 | } 54 | 55 | public someMethod() { 56 | // algo de código 57 | } 58 | 59 | private someUtility() { 60 | // algo de código 61 | } 62 | } 63 | 64 | export = new Foo(); 65 | ``` 66 | 67 | Y no son solo desarrolladores, las herramientas de desarrollo que proveen buenas visualizaciones de clases son mucho mas comunes, y hay un patrón menos que su equipo deberá entender y mantener. 68 | 69 | > P.D.: No hay anda de malo, en nuestra opinión, con jerarquías *superficiales* de clases si posibilitan su reutilización y reducen la repetición. 70 | -------------------------------------------------------------------------------- /docs/tips/create-arrays.md: -------------------------------------------------------------------------------- 1 | ## Creating arrays 2 | 3 | Creating an empty array is super easy: 4 | 5 | ```ts 6 | const foo:string[] = []; 7 | ``` 8 | 9 | If you want to create an array pre-filled with some content use the ES6 `Array.prototype.fill`: 10 | 11 | ```ts 12 | const foo:string[] = new Array(3).fill(''); 13 | console.log(foo); // ['','','']; 14 | ``` 15 | -------------------------------------------------------------------------------- /docs/tips/currying.md: -------------------------------------------------------------------------------- 1 | ## Currificiar 2 | 3 | Usen una cadena de funciones de flecha gorda: 4 | 5 | ```ts 6 | // Una función currificada 7 | let add = (x: number) => (y: number) => x + y; 8 | 9 | // Caso de uso simple 10 | add(123)(456); 11 | 12 | // Aplicado parcialmente 13 | let add123 = add(123); 14 | 15 | // Aplicar la función en su totalidad 16 | add123(456); 17 | ``` 18 | -------------------------------------------------------------------------------- /docs/tips/functionParameters.md: -------------------------------------------------------------------------------- 1 | # Function Parameters 2 | 3 | If you have a function that takes too many parameters, or parameters of the same type, then you might want to consider changing the function to take an object instead. 4 | 5 | Consider the following function: 6 | 7 | ```ts 8 | function foo(flagA: boolean, flagB: boolean) { 9 | // your awesome function body 10 | } 11 | ``` 12 | 13 | With such a function definition it's quite easy to invoke it incorrectly e.g. `foo(flagB, flagA)` and you would get no help from the compiler. 14 | 15 | Instead, convert the function to take an object: 16 | 17 | ```ts 18 | function foo(config: {flagA: boolean, flagB: boolean}) { 19 | const {flagA, flagB} = config; 20 | // your awesome function body 21 | } 22 | ``` 23 | Now the function calls will look like `foo({flagA, flagB})` which makes it much easier to spot mistakes and code review. 24 | 25 | > Note : If your function is simple enough, and you don't expect much churn, then feel free to ignore this advice 🌹. 26 | -------------------------------------------------------------------------------- /docs/tips/jquery.md: -------------------------------------------------------------------------------- 1 | ## Pistas JQuery 2 | 3 | Nota: necesitarán instalar el archivo `jquery.d.ts` para estas pistas 4 | 5 | ### definan un plugin de forma rápida 6 | 7 | Creen un archivo `jquery-foo.d.ts` con: 8 | 9 | ```ts 10 | interface JQuery { 11 | foo: any; 12 | } 13 | ``` 14 | 15 | Y podrán usar `$('something').foo({whateverYouWant:'hello jquery plugin'})` 16 | -------------------------------------------------------------------------------- /docs/tips/main.md: -------------------------------------------------------------------------------- 1 | # Consejos 2 | En esta sección presentaremos una serie de consejos que hemos juntado a través de usar TypeScript en el mundo real. 3 | -------------------------------------------------------------------------------- /docs/tips/propertySetters.md: -------------------------------------------------------------------------------- 1 | ## Limiten el uso de setters de propiedades 2 | 3 | Prefieran usar funciones set/get explícitas (e.g. `setBar` y `getBar`) por sobre setters/getters. 4 | 5 | Consideren el siguiente código: 6 | 7 | ```ts 8 | foo.bar = { 9 | a: 123, 10 | b: 456 11 | }; 12 | ``` 13 | 14 | En la presencia de setters/getters: 15 | 16 | ```ts 17 | class Foo { 18 | a: number; 19 | b: number; 20 | set bar(value:{a:number,b:number}) { 21 | this.a = value.a; 22 | this.b = value.b; 23 | } 24 | } 25 | let foo = new Foo(); 26 | ``` 27 | 28 | Este no es un *buen* uso de setters de propiedades. La persona que lea la primera muestra de código no tiene nada de contexto sobre todas las cosas que cambiarán. Por otro lado, alquien que llama a `foo.setBar(value)` puede tener una idea que algo cambiará en `foo`. 29 | 30 | > Puntos bonus: Encontramos que las referencias funcionan mejor si tienen funciones diferentes. En las herramientas de TypeScript, si encuentran referencias para un getter o un setter, obtendrán *ambas* mientras que con llamadas explícitas a funciones solo obtendrán la referencias a la función relevante. 31 | -------------------------------------------------------------------------------- /docs/tips/singleton.md: -------------------------------------------------------------------------------- 1 | # Singleton Pattern 2 | 3 | The conventional singleton pattern is really something that is used to overcome the fact that all code must be in a `class`. 4 | 5 | ```ts 6 | class Singleton { 7 | private static instance: Singleton; 8 | private constructor() { 9 | // do something construct... 10 | } 11 | static getInstance() { 12 | if (!Singleton.instance) { 13 | Singleton.instance = new Singleton(); 14 | // ... any one time initialization goes here ... 15 | } 16 | return Singleton.instance; 17 | } 18 | someMethod() { } 19 | } 20 | 21 | let something = new Singleton() // Error: constructor of 'Singleton' is private. 22 | 23 | let instance = Singleton.getInstance() // do something with the instance... 24 | ``` 25 | 26 | However, if you don't want lazy initialization you can instead just use a `namespace`: 27 | 28 | ```ts 29 | namespace Singleton { 30 | // ... any one time initialization goes here ... 31 | export function someMethod() { } 32 | } 33 | // Usage 34 | Singleton.someMethod(); 35 | ``` 36 | 37 | > Warning : Singleton is just a fancy name for [global](http://stackoverflow.com/a/142450/390330) 38 | 39 | For most projects `namespace` can additionally be replaced by a *module*. 40 | 41 | ```ts 42 | // someFile.ts 43 | // ... any one time initialization goes here ... 44 | export function someMethod() { } 45 | 46 | // Usage 47 | import {someMethod} from "./someFile"; 48 | ``` 49 | 50 | 51 | -------------------------------------------------------------------------------- /docs/tips/statefulFunctions.md: -------------------------------------------------------------------------------- 1 | ## Funciones con estado 2 | Una característica común de otros lenguajes de programación es el uso de la palabra clave `static` para incrementar el *tiempo de vida* (no el *ámbito*) de una variable de función para que viva por fuera de invocaciones de la función. Aquí mostramos un ejemplo `C` que hace uso de esta característica: 3 | 4 | ```c 5 | void called() { 6 | static count = 0; 7 | count++; 8 | printf("Called : %d", count); 9 | } 10 | 11 | int main () { 12 | called(); // Called : 1 13 | called(); // Called : 2 14 | return 0; 15 | } 16 | ``` 17 | 18 | Debido a que JavaScript (o TypeScript) no tienen funciones estáticas, esto puede ser logrado usando varias abstracciones que envuelven una variable local. Por ejemplo, usando una `clase`: 19 | 20 | ```ts 21 | const {called} = new class { 22 | count = 0; 23 | called = () => { 24 | this.count++; 25 | console.log(`Called : ${this.count}`); 26 | } 27 | }; 28 | 29 | called(); // Called : 1 30 | called(); // Called : 2 31 | ``` 32 | 33 | > Los desarrolladores C++ también intentan lograr esto usando un patrón llamado `functor` (una clase que anula el operador `()`). 34 | -------------------------------------------------------------------------------- /docs/tips/staticConstructor.md: -------------------------------------------------------------------------------- 1 | # Constructores Estáticos en TypeScript 2 | 3 | Las `clases` de TypeScript (como las `clases` de JavaScript) no pueden tener un constructor estático. Sin embargo, pueden obtener el mismo efecto fácilmente al llamarlo ustedes mismos: 4 | 5 | ```ts 6 | class MyClass { 7 | static initialize() { 8 | // Inicialización 9 | } 10 | } 11 | MyClass.initialize(); 12 | ``` 13 | -------------------------------------------------------------------------------- /docs/tips/stringEnums.md: -------------------------------------------------------------------------------- 1 | ## String enums 2 | 3 | A veces necesitarán un conjunto de strings agrupadas bajo una clave en común. Antes de TypeScript 2.4, TypeScript solo soportaba enums basadas en números. Si estan usando una versión anterior a 2.4, una forma de resolver este problema es [usar tipos string literales para crear enums basadas en strings combinándolas con tipos unión](../types/literal-types.md). 4 | -------------------------------------------------------------------------------- /docs/tips/typeInstantiation.md: -------------------------------------------------------------------------------- 1 | ## Instanciación de Tipos para Genéricos 2 | 3 | Hagan de cuenta que tienen algo que tiene un parámetro genérico. Por ejemplo, una clase `Foo`: 4 | 5 | ```ts 6 | class Foo{ 7 | foo: T; 8 | } 9 | ``` 10 | 11 | Quieren crearle una versión especializada para un tipo en particular. El patrón consiste en copiar el item a una variable nueva y darle la anotación de tipo reemplazando los genéricos por tipos concretos. Por ejemplo, si quieren una clase `Foo`: 12 | 13 | ```ts 14 | class Foo{ 15 | foo: T; 16 | } 17 | let FooNumber = Foo as { new ():Foo }; // ref 1 18 | ``` 19 | En `ref1` están indicando que `FooNumber` es lo mismo que `Foo`, pero que debe ser tratada como algo que cuando es llamada con el operador `new` dará una instancia de `Foo`. 20 | 21 | ### Herencia 22 | El patrón de aserción de tipos es inseguro ya que confía en que ustedes harán lo correcto. Un patrón común en otros lenguajes (*en lo que respecta a clases*) es usar la herencia: 23 | 24 | ```ts 25 | class FooNumber extends Foo{} 26 | ``` 27 | 28 | Una advertencia: si usan decoradores en la clase base, entonces la clase heredada puede no comportarse de la misma manera que la clase base (ya que no se encontrará envuelta por el decorador). 29 | 30 | Si no están especializando las clases, igual tendrán que pensar un patrón de coerción / aserción que funcione. De ahí que hemos mostrado el patrón de aserción general primero. Por ejemplo: 31 | 32 | ```ts 33 | function id(x: T) { return x; } 34 | const idNum = id as {(x:number):number}; 35 | ``` 36 | 37 | > Inspirirado por esta [pregunta de stackoverflow](http://stackoverflow.com/a/34864705/390330) 38 | -------------------------------------------------------------------------------- /docs/tips/typed-event.md: -------------------------------------------------------------------------------- 1 | ## Typesafe Event Emitter 2 | 3 | Conventionally in Node.js and traditional JavaScript you have a single event emitter. This event emitter internally tracks listener for different event types e.g. 4 | 5 | ```ts 6 | const emitter = new EventEmitter(); 7 | // Emit: 8 | emitter.emit('foo', foo); 9 | emitter.emit('bar', bar); 10 | // Listen: 11 | emitter.on('foo', (foo)=>console.log(foo)); 12 | emitter.on('bar', (bar)=>console.log(bar)); 13 | ``` 14 | Essentially `EventEmitter` internally stores data in the form of mapped arrays: 15 | ```ts 16 | {foo: [fooListeners], bar: [barListeners]} 17 | ``` 18 | Instead, for the sake of *event* type safety, you can create an emitter *per* event type: 19 | ```ts 20 | const onFoo = new TypedEvent(); 21 | const onBar = new TypedEvent(); 22 | 23 | // Emit: 24 | onFoo.emit(foo); 25 | onBar.emit(bar); 26 | // Listen: 27 | onFoo.on((foo)=>console.log(foo)); 28 | onBar.on((bar)=>console.log(bar)); 29 | ``` 30 | 31 | This has the following advantages: 32 | * The types of events are easily discoverable as variables. 33 | * The event emitter variables are easily refactored independently. 34 | * Type safety for event data structures. 35 | 36 | ### Reference TypedEvent 37 | ```ts 38 | export interface Listener { 39 | (event: T): any; 40 | } 41 | 42 | export interface Disposable { 43 | dispose(); 44 | } 45 | 46 | /** passes through events as they happen. You will not get events from before you start listening */ 47 | export class TypedEvent { 48 | private listeners: Listener[] = []; 49 | private listenersOncer: Listener[] = []; 50 | 51 | on = (listener: Listener): Disposable => { 52 | this.listeners.push(listener); 53 | return { 54 | dispose: () => this.off(listener) 55 | }; 56 | } 57 | 58 | once = (listener: Listener): void => { 59 | this.listenersOncer.push(listener); 60 | } 61 | 62 | off = (listener: Listener) => { 63 | var callbackIndex = this.listeners.indexOf(listener); 64 | if (callbackIndex > -1) this.listeners.splice(callbackIndex, 1); 65 | } 66 | 67 | emit = (event: T) => { 68 | /** Update any general listeners */ 69 | this.listeners.forEach((listener) => listener(event)); 70 | 71 | /** Clear the `once` queue */ 72 | this.listenersOncer.forEach((listener) => listener(event)); 73 | this.listenersOncer = []; 74 | } 75 | 76 | pipe = (te: TypedEvent): Disposable => { 77 | return this.on((e) => te.emit(e)); 78 | } 79 | } 80 | ``` 81 | -------------------------------------------------------------------------------- /docs/tools/changelog.md: -------------------------------------------------------------------------------- 1 | ## Changelog 2 | > Leer un archivo markdown con el progreso en el proyecto es más fácil que leer un registro de commits. 3 | 4 | La generación automática de regitros de cambios a partir de mensaje sde commits es un patrón bastante común actualmente. Hay un proyecto llamado [conventional-changelog](https://github.com/conventional-changelog/conventional-changelog) que genera un registro de cambios a partir de mensajes de commits siguiendo una *convención*. 5 | 6 | ### Convención de mensajes de commits 7 | La convención más popular es la de *angular*, que se encuentra [detallada aquí (https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines). 8 | 9 | ### Configuración 10 | * Instalar: 11 | 12 | ```bash 13 | npm install standard-version -D 14 | ``` 15 | 16 | * Agreguen una `serie de comandos` target a su `package.json`: 17 | 18 | ```js 19 | { 20 | "scripts": { 21 | "release": "standard-version" 22 | } 23 | } 24 | ``` 25 | 26 | * Opcional: Para empujar el nuevo *git commit y tag* automáticamente y publicarlo a npm agreguen una serie de comandos `postrelease`: 27 | 28 | ```js 29 | { 30 | "scripts": { 31 | "release": "standard-version", 32 | "postrelease": "git push --follow-tags origin master && npm publish" 33 | } 34 | } 35 | ``` 36 | 37 | ### Publicación 38 | 39 | Corran: 40 | 41 | ```bash 42 | npm run release 43 | ``` 44 | 45 | El tipo de publicación `major` | `minor` | `patch` se determina automáticamente. Para especificar una versión *explícitamente* deben usar la bandera `--release-as`. Por ejemplo: 46 | 47 | ```bash 48 | npm run release -- --release-as minor 49 | ``` 50 | -------------------------------------------------------------------------------- /docs/tools/eslint.md: -------------------------------------------------------------------------------- 1 | # ESLint 2 | 3 | ESLint existed to lint JavaScript, but now it is also becoming the defacto linter for [TypeScript](https://github.com/Microsoft/TypeScript/issues/29288), thanks to the [collaboration](https://eslint.org/blog/2019/01/future-typescript-eslint) between the two teams. 4 | 5 | ## Install 6 | 7 | To setup ESLint for TypeScript you need the following packages: 8 | 9 | ```sh 10 | npm i eslint eslint-plugin-react @typescript-eslint/parser @typescript-eslint/eslint-plugin 11 | ``` 12 | 13 | > TIP: eslint calls packages that contain lint rules as "plugin" 14 | 15 | * eslint : Core eslint 16 | * eslint-plugin-react : For react rules provided by eslint. [Supported rules list](https://github.com/yannickcr/eslint-plugin-react#list-of-supported-rules) 17 | * @typescript-eslint/parse : To allow eslint to understand ts / tsx files 18 | * @typescript-eslint/eslint-plugin : For TypeScript rules. [Supported rules list](https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#supported-rules) 19 | 20 | > As you can see there are two eslint packages (for use with js or ts) and two @typescript-eslint packages (for use with ts). So the overhead for TypeScript is not *that much*. 21 | 22 | ## Configure 23 | Create `.eslintrc.js`: 24 | 25 | ```js 26 | module.exports = { 27 | parser: '@typescript-eslint/parser', 28 | parserOptions: { 29 | project: './tsconfig.json', 30 | }, 31 | plugins: ['@typescript-eslint'], 32 | extends: [ 33 | 'plugin:react/recommended', 34 | 'plugin:@typescript-eslint/recommended', 35 | ], 36 | rules: { 37 | // Overwrite rules specified from the extended configs e.g. 38 | // "@typescript-eslint/explicit-function-return-type": "off", 39 | } 40 | } 41 | ``` 42 | 43 | ## Run 44 | 45 | In your `package.json` add to `scripts`: 46 | 47 | ```json 48 | { 49 | "scripts": { 50 | "lint": "eslint src/**" 51 | } 52 | } 53 | ``` 54 | 55 | Now you can `npm run lint` to validate. 56 | 57 | ## Configure VSCode 58 | 59 | * Install extension https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint 60 | * Add to `settings.json`: 61 | ```js 62 | "eslint.validate": [ 63 | "javascript", 64 | "javascriptreact", 65 | {"language": "typescript", "autoFix": true }, 66 | {"language": "typescriptreact", "autoFix": true } 67 | ], 68 | ``` 69 | -------------------------------------------------------------------------------- /docs/tools/husky.md: -------------------------------------------------------------------------------- 1 | # Husky 2 | 3 | > Husky puede prevenir commits malos, pushes y más 🐶! 4 | 5 | Si quieren correr código JavaScript / TypeSCript antes de que un commit ocurra, husky es la herramienta indicada. 6 | 7 | Por ejemplo, pueden usar husky para asegurarse que los archivos sean formateados automáticamente por prettier para que no tengan que preocuparse de hacerlo manualmente nunca más, y así concentrarse únicamente en el código. Aquí esta la configuración: 8 | 9 | * `npm install husky -D` 10 | * Agregar las `series de comandos` a `package.json`: 11 | 12 | ``` 13 | "precommit": "npm run prettier:write", 14 | ``` 15 | 16 | Ahora cada vez que commitan código y hayan correcciones de formato para hacer, las recibirán como un archivo *modificado* en el registro de git. Esto les permitirá 17 | 18 | * si ya han empujado su código a remote, pueden hacer un commit nuevo con un comentario `pretty`. 19 | * si todavia no han empujado su código, corrijan su último commit y parezcan un superhéroe. 20 | -------------------------------------------------------------------------------- /docs/tools/intro.md: -------------------------------------------------------------------------------- 1 | # Herramientas 2 | Acá listamos algunas de las herramientas que les recomendamos usar (o al menos probar) en sus proyectos TypeScript. 3 | -------------------------------------------------------------------------------- /docs/tools/prettier.md: -------------------------------------------------------------------------------- 1 | # Prettier 2 | 3 | Prettier es una gran herramienta desarrollada por Facebook que facilita tanto el proceso de formateo de código que amerita mencionarla. Incluirla en un proyecto TypeScript usando nuestra preparación de proyectos recomendada (es decir, todo en la carpeta `src`) es súper fácil: 4 | 5 | ## Preparación 6 | 7 | * `npm install prettier -D` 8 | * Agregar `series de comandos` a `package.json`: 9 | 10 | ``` 11 | "prettier:base": "prettier --parser typescript --single-quote", 12 | "prettier:check": "npm run prettier:base -- --list-different \"src/**/*.{ts,tsx}\"", 13 | "prettier:write": "npm run prettier:base -- --write \"src/**/*.{ts,tsx}\"" 14 | ``` 15 | 16 | ## Uso 17 | En el servidor de construcción: 18 | * `npm run prettier:check` 19 | 20 | Durante desarrollo (o como enganche de pre commit): 21 | * `npm run prettier:write` 22 | -------------------------------------------------------------------------------- /docs/types/@types.md: -------------------------------------------------------------------------------- 1 | # `@types` 2 | 3 | [Definitely Typed](https://github.com/DefinitelyTyped/DefinitelyTyped) es una de las fortalezas más grandes de TypeScript. La comunidad ha procedido a **documentar** la naturaleza de casi 90% de los proyectos JavaScript más populares. 4 | 5 | Esto significa que pueden usar estos proyectos de manera interactiva y exploratoria, sin necesidad de tener la documentación abierta en una ventana separada y asegurandose que no cometen un error de tipeo. 6 | 7 | ## Usando `@types` 8 | 9 | La instalación es sencilla ya que funciona sobre `npm`. A modo de ejemplo, pueden instalar definciones de tipo para `jquery` simplemente con: 10 | 11 | ``` 12 | npm install @types/jquery --save-dev 13 | ``` 14 | 15 | `@types` soporta definiciones de tipo tanto *globales* como *modulares*. 16 | 17 | 18 | ### `@types` globales 19 | 20 | Por default, caulquier definición que soporte consumisión global se encuentra incluída automáticamente. Por ejemplo, para `jquery` deberían poder comenzar a usar `$` *globalmente* en su proyecto sin problema. 21 | 22 | Sin embargo, para *librerías* (como `jquery`) en general recomendamos usar *módulos*: 23 | 24 | ### `@types` modulares 25 | 26 | Luego de la instalación, no es necesario realizar ninguna configuración especial. Simplemente utilizarlo como un módulo. Por ejemplo: 27 | 28 | ```ts 29 | import * as $ from "jquery"; 30 | 31 | // Usen $ como deseen en este módulo :) 32 | ``` 33 | 34 | ## Controlando globales 35 | 36 | Como pueden observar, tener una definicón que permite acceso gloabl automáticamente puede ser un problema para algunos equipos. Por eso, pueden elegir 37 | 38 | As can be seen, having a definition that allows global leak-in automatically can be a problem for some teams. Por lo tanto, puede elegir * explícitamente * solo incorporar los tipos que tienen sentido usando las `compilerOption.types` de `tsconfig.json`. Por ejemplo: 39 | 40 | ```json 41 | { 42 | "compilerOptions": { 43 | "types" : [ 44 | "jquery" 45 | ] 46 | } 47 | } 48 | ``` 49 | 50 | Este es un ejemplo en el que solo `jquery` tendrá permitido su uso. Incluso si una persona instala otra definición con `npm install @types/node` sus globales (e.g. [`process`](https://nodejs.org/api/process.html)) no aparecerán en tu código hasta que las agreguen a la opción de tipos de `tsconfig.json`. 51 | -------------------------------------------------------------------------------- /docs/types/ambient/d.ts.md: -------------------------------------------------------------------------------- 1 | ### Archivo de declaración 2 | Pueden decirle a TypeScript que estan tratando de describir código que existe en otro lado (por ejemplo, escrito JavaScript/CoffeeScript/en un ambiente de ejecución como el navegador o Node.js) usando la palabra clave `declare`. A modo de ejemplo rápido: 3 | 4 | ```ts 5 | foo = 123; // Error: `foo` no está definido 6 | ``` 7 | vs. 8 | ```ts 9 | declare var foo: any; 10 | foo = 123; // permitido 11 | ``` 12 | 13 | Tienen la opción de poner estas declaraciones en un archivo `.ts` o en un archivo `.d.ts`. Nosotros recomendamos que en sus proyectos reales usen un `d.ts` separado. Comiencen con un archivo llamado `globals.d.ts` o `vendor.d.ts`, o algo similar. 14 | 15 | Si un archivo tiene la extensión `.d.ts`, etnonces cada definición a nivel raíz debe tener la palabra clave `declare` precediéndola. Esto ayuda a clarificarle al autor que *no habrá código emitido por TypeScript*. El autor debe asegurarse que el ítem declarado existirá al momento de ejecución. 16 | 17 | > * Las declaraciones ambiente son una promesa que estan haciendo con el compilador. Si estas no existen en el momento de ejecución y ustedes intentan utilizarlas, las cosas se romperan sin advertencia previa. 18 | * Las declaraciones ambiente son como documentación. Si la fuente cambia, la documentación debe ser actualizada. Por lo que tal vez tengan nuevos comportamientos que funcionan en tiempo de ejecución pero nadie actualizó las declaraciones de ambiente y, por ende, recibirián errores de compilación. 19 | -------------------------------------------------------------------------------- /docs/types/ambient/intro.md: -------------------------------------------------------------------------------- 1 | ## Declaraciones Ambiente 2 | 3 | Como mencioneamos en [Por qué TypeScript](../../why-typescript.md): 4 | 5 | > Uno de los objetivos de diseño principales de TypeScript era posibilitar que usen librerias JavaScript existentes de forma segura y fácilmente en TypeScript. TypeScript hace esto mediante las *declaraciones*. 6 | 7 | Las declaraciones de Ambiente les permite *usar librerías JavaScript populares de forma segura* y *migrar sus proyectos escritos con código JavaScript/CoffeeScript/Otro-Lenguage-Que-Compila-A-Js a TypeScript*. 8 | 9 | Estudiar los patrones en declaraciones ambientes para *código JavaScript escrito por terceros* es una buena práctica para anotar *su propio código* también. Por esto lo presentamos al comienzo. 10 | -------------------------------------------------------------------------------- /docs/types/ambient/variables.md: -------------------------------------------------------------------------------- 1 | ### Variables 2 | Para contarle a TypeScript sobre la [variable `process`](https://nodejs.org/api/process.html), por ejemplo, *pueden*: 3 | 4 | ```ts 5 | declare var process: any; 6 | ``` 7 | 8 | > No *necesitan* hacer esto para `process` ya que ya existe un [`node.d.ts` mantenido por la comunidad(https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/node/index.d.ts). 9 | 10 | Esto les permitirá usar la variable `process` sin que TypeScript se queje: 11 | 12 | ```ts 13 | process.exit(); 14 | ``` 15 | 16 | Recomendamos usar una interface en donde sea posible. Por ejemplo: 17 | 18 | ```ts 19 | interface Process { 20 | exit(code?: number): void; 21 | } 22 | declare var process: Process; 23 | ``` 24 | 25 | Esto le permite a otras personas *extender* la naturaleza de estas variables globales y mantener a TypeScript informado sobre los cambios. Por ejemplo, consideremos el siguiente caso donde agregamos una función `exitWithLogging` a `process` para nuestro entretenimiento: 26 | 27 | ```ts 28 | interface Process { 29 | exitWithLogging(code?: number): void; 30 | } 31 | process.exitWithLogging = function() { 32 | console.log("exiting"); 33 | process.exit.apply(process, arguments); 34 | }; 35 | ``` 36 | 37 | Procedamos a mirar las interfaces con mayor nivel de detalle. 38 | -------------------------------------------------------------------------------- /footer.md: -------------------------------------------------------------------------------- 1 | [![fork me](/images/github.png) Fork me on github](https://github.com/basarat/typescript-book/) 2 | -------------------------------------------------------------------------------- /header.html: -------------------------------------------------------------------------------- 1 | 15 | -------------------------------------------------------------------------------- /images/atomts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melissarofman/typescript-book/aa9ca251cb7b4616183c0e2045a48a581d1d83c0/images/atomts.png -------------------------------------------------------------------------------- /images/errors/interpreting-errors/ide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melissarofman/typescript-book/aa9ca251cb7b4616183c0e2045a48a581d1d83c0/images/errors/interpreting-errors/ide.png -------------------------------------------------------------------------------- /images/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melissarofman/typescript-book/aa9ca251cb7b4616183c0e2045a48a581d1d83c0/images/github.png -------------------------------------------------------------------------------- /images/promise states and fates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melissarofman/typescript-book/aa9ca251cb7b4616183c0e2045a48a581d1d83c0/images/promise states and fates.png -------------------------------------------------------------------------------- /images/promise states and fates.vsd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melissarofman/typescript-book/aa9ca251cb7b4616183c0e2045a48a581d1d83c0/images/promise states and fates.vsd -------------------------------------------------------------------------------- /images/venn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melissarofman/typescript-book/aa9ca251cb7b4616183c0e2045a48a581d1d83c0/images/venn.png -------------------------------------------------------------------------------- /images/venn.vsd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melissarofman/typescript-book/aa9ca251cb7b4616183c0e2045a48a581d1d83c0/images/venn.vsd -------------------------------------------------------------------------------- /snippets/md-snippets.cson: -------------------------------------------------------------------------------- 1 | '.source.gfm': 2 | 'include': 3 | 'prefix': 'include' 4 | 'body': """ 5 | {% include "${1:./path}.md" %} 6 | """ --------------------------------------------------------------------------------