├── .gitattributes ├── .gitignore ├── CONTRIBUTING.md ├── GLOSSARY.md ├── LICENSE.md ├── README.md ├── SUMMARY.md ├── book.json ├── browser.md ├── 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 ├── compiler-options.md ├── compiler │ ├── binder-symbolflags.md │ └── make-global.md ├── declaration.md ├── project │ └── module-resolution.md ├── staging │ ├── async-await.md │ └── generators.md ├── styleguide │ ├── sample.js │ ├── sample.ts │ └── tsconfig.json └── types │ └── advanced.md ├── footer.md ├── future-javascript ├── README.md ├── arrow-functions.md ├── async-await.md ├── classes │ ├── README.md │ └── classes-emit.md ├── const.md ├── destructuring.md ├── for...of.md ├── generators.md ├── iterators.md ├── let.md ├── promise.md ├── rest-parameters.md ├── spread-operator.md └── template-strings.md ├── getting-started ├── README.md └── why-typescript.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 └── venn_pt.png ├── index.md ├── intro-1 ├── README.md ├── cypress.md └── jest.md ├── intro-2 ├── README.md ├── changelog.md ├── husky.md └── prettier.md ├── intro ├── README.md ├── noimplicitany.md └── strictnullchecks.md ├── main-1 ├── README.md ├── barrel.md ├── bind.md ├── build-toggles.md ├── classesareuseful.md ├── create-arrays.md ├── currying.md ├── defaultisbad.md ├── functionparameters.md ├── jquery.md ├── lazyobjectliteralinitialization.md ├── nominaltyping.md ├── outfile.md ├── propertysetters.md ├── singleton.md ├── statefulfunctions.md ├── staticconstructor.md ├── stringenums.md ├── typed-event.md └── typeinstantiation.md ├── main ├── README.md ├── common-errors.md └── interpreting-errors.md ├── nodejs.md ├── overview ├── README.md ├── ast │ ├── README.md │ ├── ast-tip-children.md │ ├── ast-tip-syntaxkind.md │ └── ast-trivia.md ├── binder │ ├── README.md │ ├── binder-container.md │ ├── binder-declarations.md │ ├── binder-diagnostics.md │ ├── binder-functions.md │ └── binder-symboltable.md ├── checker │ ├── README.md │ ├── checker-diagnostics.md │ └── checker-global.md ├── contributing.md ├── emitter │ ├── README.md │ ├── emitter-functions.md │ └── emitter-sourcemaps.md ├── parser │ ├── README.md │ └── parser-functions.md ├── program.md └── scanner.md ├── project ├── README.md ├── compilation-context │ ├── README.md │ ├── files.md │ └── tsconfig.md ├── declarationspaces.md ├── dynamic-import-expressions.md ├── modules │ ├── README.md │ ├── external-modules.md │ └── globals.md └── namespaces.md ├── recap ├── README.md ├── closure.md ├── equality.md ├── null-undefined.md ├── number.md ├── references.md ├── this.md └── truthy.md ├── snippets └── md-snippets.cson ├── styleguide.md ├── tsx ├── README.md ├── others.md └── react.md └── type-system ├── README.md ├── callable.md ├── discriminated-unions.md ├── enums.md ├── exceptions.md ├── freshness.md ├── functions.md ├── generics.md ├── index-signatures.md ├── interfaces.md ├── intro ├── README.md ├── d.ts.md └── variables.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 ├── typeguard.md └── types.md /.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 | Se anda como um pato e grita como um pato, é um pato. Para o TypeScript, se tiver todos os membros estruturalmente, não há problema em outras coisas (independentemente do nome) que aceitem essa estrutura. 3 | 4 | # OE 5 | Ambiente operacional. Eu gostaria de usar o termo Sistema Operacional, mas isso não é necessariamente o que quero dizer aqui. Pense no navegador, no Node.js, no WScriptHost etc. 6 | 7 | # Análise Incremental 8 | Analisando novamente conforme o usuário edita o código. -------------------------------------------------------------------------------- /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 | // async function always return a Promise 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 | // async function always return a Promise 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 | // async function always return a Promise 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 has all of the proper types, autocomplete works, 6 | // type checking works, code references work \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 has all of the proper types, autocomplete works, 6 | // type checking works, code references work \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/overlineink/typescript-book/931d8c2f3adb433808e8ca689687bd24624280f4/code/es6/test.js -------------------------------------------------------------------------------- /code/es6/test.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overlineink/typescript-book/931d8c2f3adb433808e8ca689687bd24624280f4/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/overlineink/typescript-book/931d8c2f3adb433808e8ca689687bd24624280f4/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/overlineink/typescript-book/931d8c2f3adb433808e8ca689687bd24624280f4/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/type-inference.js: -------------------------------------------------------------------------------- 1 | var Definition; 2 | (function (Definition) { 3 | var foo = 123; 4 | var bar = "Hello"; 5 | foo = bar; 6 | })(Definition || (Definition = {})); 7 | var ReturnType; 8 | (function (ReturnType) { 9 | function add(a, b) { 10 | return a + b; 11 | } 12 | })(ReturnType || (ReturnType = {})); 13 | var Assignment; 14 | (function (Assignment) { 15 | var foo = function (a, b) { return a + b; }; 16 | })(Assignment || (Assignment = {})); 17 | var AssignmentErrorOut; 18 | (function (AssignmentErrorOut) { 19 | var foo = function (a, b) { 20 | a = "hello"; 21 | return a + b; 22 | }; 23 | })(AssignmentErrorOut || (AssignmentErrorOut = {})); 24 | var AssignmentAsCallback; 25 | (function (AssignmentAsCallback) { 26 | function iTakeAnAdder(adder) { 27 | return adder(1, 2); 28 | } 29 | iTakeAnAdder(function (a, b) { 30 | return a + b; 31 | }); 32 | })(AssignmentAsCallback || (AssignmentAsCallback = {})); 33 | var Structuring; 34 | (function (Structuring) { 35 | var foo = { 36 | a: 123, 37 | b: 456 38 | }; 39 | var bar = [1, 2, 3]; 40 | })(Structuring || (Structuring = {})); 41 | var StructuringDeep; 42 | (function (StructuringDeep) { 43 | var foo = { 44 | bar: [1, 3, 4] 45 | }; 46 | foo.bar[0] = 'hello'; 47 | })(StructuringDeep || (StructuringDeep = {})); 48 | var DeStructuring; 49 | (function (DeStructuring) { 50 | var foo = { 51 | a: 123, 52 | b: 456 53 | }; 54 | var a = foo.a; 55 | })(DeStructuring || (DeStructuring = {})); 56 | var DeStructuringArrays; 57 | (function (DeStructuringArrays) { 58 | var bar = [1, 2]; 59 | var a = bar[0], b = bar[1]; 60 | })(DeStructuringArrays || (DeStructuringArrays = {})); 61 | var DeStructuringArguments; 62 | (function (DeStructuringArguments) { 63 | function iTakeAnAdder(adder) { 64 | return adder({ a: 1, b: 2 }); 65 | } 66 | iTakeAnAdder(function (_a) { 67 | var a = _a.a, b = _a.b; 68 | return a + b; 69 | }); 70 | })(DeStructuringArguments || (DeStructuringArguments = {})); 71 | var CantInferArguments; 72 | (function (CantInferArguments) { 73 | var foo = function (a, b) { }; 74 | })(CantInferArguments || (CantInferArguments = {})); 75 | var CanInferArguments; 76 | (function (CanInferArguments) { 77 | var foo = function (a, b) { }; 78 | })(CanInferArguments || (CanInferArguments = {})); 79 | var CannotInferReturn; 80 | (function (CannotInferReturn) { 81 | function foo(a, b) { 82 | return a + addOne(b); 83 | } 84 | function addOne(a) { 85 | return a + 1; 86 | } 87 | })(CannotInferReturn || (CannotInferReturn = {})); 88 | -------------------------------------------------------------------------------- /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/overlineink/typescript-book/931d8c2f3adb433808e8ca689687bd24624280f4/cover.jpg -------------------------------------------------------------------------------- /docs/compiler-options.md: -------------------------------------------------------------------------------- 1 | // mention Pinned comments 2 | 3 | ```ts 4 | /*! 5 | * License 6 | */ 7 | ``` 8 | -------------------------------------------------------------------------------- /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/declaration.md: -------------------------------------------------------------------------------- 1 | analogy with c headers 2 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /footer.md: -------------------------------------------------------------------------------- 1 | [![fork me](/images/github.png) Fork me on github](https://github.com/basarat/typescript-book/) 2 | -------------------------------------------------------------------------------- /future-javascript/README.md: -------------------------------------------------------------------------------- 1 | # Futuro JavaScript Agora 2 | 3 | One of the main selling points of TypeScript is that it allows you to use a bunch of features from ES6 and beyond in current \(ES3 and ES5 level\) JavaScript engines \(like current browsers and Node.js\). Here we deep dive into why these features are useful followed by how these features are implemented in TypeScript. 4 | 5 | Note: Not all of these features are slated for immediate addition to JavaScript but provide great utility to your code organization and maintenance. Also note that you are free to ignore any of the constructs that don't make sense for your project, although you will end up using most of them eventually ;\) 6 | 7 | -------------------------------------------------------------------------------- /future-javascript/const.md: -------------------------------------------------------------------------------- 1 | # const 2 | 3 | `const` is a very welcomed addition offered by ES6 / TypeScript. It allows you to be immutable with variables. This is good from a documentation as well as a runtime perspective. To use const just replace `var` with `const`: 4 | 5 | ```typescript 6 | const foo = 123; 7 | ``` 8 | 9 | > The syntax is much better \(IMHO\) than other languages that force the user to type something like `let constant foo` i.e. a variable + behavior specifier. 10 | 11 | `const` is a good practice for both readability and maintainability and avoids using _magic literals_ e.g. 12 | 13 | ```typescript 14 | // Low readability 15 | if (x > 10) { 16 | } 17 | 18 | // Better! 19 | const maxRows = 10; 20 | if (x > maxRows) { 21 | } 22 | ``` 23 | 24 | ## const declarations must be initialized 25 | 26 | The following is a compiler error: 27 | 28 | ```typescript 29 | const foo; // ERROR: const declarations must be initialized 30 | ``` 31 | 32 | ## Left hand side of assignment cannot be a constant 33 | 34 | Constants are immutable after creation, so if you try to assign them to a new value it is a compiler error: 35 | 36 | ```typescript 37 | const foo = 123; 38 | foo = 456; // ERROR: Left-hand side of an assignment expression cannot be a constant 39 | ``` 40 | 41 | ## Block Scoped 42 | 43 | A `const` is block scoped like we saw with [`let`](let.md): 44 | 45 | ```typescript 46 | const foo = 123; 47 | if (true) { 48 | const foo = 456; // Allowed as its a new variable limited to this `if` block 49 | } 50 | ``` 51 | 52 | ## Deep immutability 53 | 54 | A `const` works with object literals as well, as far as protecting the variable _reference_ is concerned: 55 | 56 | ```typescript 57 | const foo = { bar: 123 }; 58 | foo = { bar: 456 }; // ERROR : Left hand side of an assignment expression cannot be a constant 59 | ``` 60 | 61 | However, it still allows sub properties of objects to be mutated, as shown below: 62 | 63 | ```typescript 64 | const foo = { bar: 123 }; 65 | foo.bar = 456; // Allowed! 66 | console.log(foo); // { bar: 456 } 67 | ``` 68 | 69 | For this reason I recommend using `const` with primitives or immutable data structures. 70 | 71 | -------------------------------------------------------------------------------- /future-javascript/rest-parameters.md: -------------------------------------------------------------------------------- 1 | # Rest Parameters 2 | 3 | Rest parameters \(denoted by `...argumentName` for the last argument\) allow you to quickly accept multiple arguments in your function and get them as an array. This is demonstrated in the below example. 4 | 5 | ```typescript 6 | function iTakeItAll(first, second, ...allOthers) { 7 | console.log(allOthers); 8 | } 9 | iTakeItAll('foo', 'bar'); // [] 10 | iTakeItAll('foo', 'bar', 'bas', 'qux'); // ['bas','qux'] 11 | ``` 12 | 13 | Rest parameters can be used in any function be it `function`/`()=>`/`class member`. 14 | 15 | -------------------------------------------------------------------------------- /getting-started/README.md: -------------------------------------------------------------------------------- 1 | # Primeiros Passos 2 | 3 | * [Iniciando no TypeScript](./#iniciando-no-typescript) 4 | * [Versão do TypeScript](./#typescript-version) 5 | 6 | ## Iniciando no TypeScript 7 | 8 | O TypeScript é compilado em JavaScript. Na verdade, é o JavaScript que você irá executar \(tanto no navegador como no servidor\). Então, você irá precisar do seguinte: 9 | 10 | * Compilador de TypeScript [disponível na fonte](https://github.com/Microsoft/TypeScript/) e via [NPM](https://www.npmjs.com/package/typescript)\) 11 | * Um editor de TypeScript \(você pode usar o bloco de notas se quiser, mas eu uso o [vscode 🌹](https://code.visualstudio.com/) com uma [extensão escrita por mim](https://marketplace.visualstudio.com/items?itemName=basarat.god). [Muitas outras IDEs também suportam o TypeScript](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Editor-Support)\) 12 | 13 | ### Versão do TypeScript 14 | 15 | Ao invés de usar compilador _stable_ \(estável\) nós vamos estar apresentando muitas coisas novas neste livro que ainda podem não estar associadas com um número de versão. Eu geralmente recomendo as pessoas a usarem a _nightly version_ porque **a Versão de testes só é capaz de capturar os bugs conforme é utilizada**. Você pode instalar através da linha de comando com 16 | 17 | ```text 18 | npm install -g typescript@next 19 | ``` 20 | 21 | E agora o comando `tsc` irá ser o mais atual e o melhor. Várias IDEs tão suportam esta versão. 22 | 23 | * Você pode pedir ao vscode para usar estar versão criando `.vscode/settings.json` com o seguinte conteúdo: 24 | 25 | ```javascript 26 | { 27 | "typescript.tsdk": "./node_modules/typescript/lib" 28 | } 29 | ``` 30 | 31 | ### Acesso ao código fonte 32 | 33 | O Código Fonte deste livro esta disponível no repositório de livros do github [https://github.com/basarat/typescript-book/tree/master/code](https://github.com/basarat/typescript-book/tree/master/code) onde maior parte dos exemplos pode ser copiada para o vscode para que você possa treinar com eles. Para os exemplos que precisam de configurações adicionais nós iremos deixar um link para o exemplo antes de mostrar o código. 34 | 35 | `este/sera/o/link/para/o/codigo.ts` 36 | 37 | ```typescript 38 | // Este será o código em discussão. 39 | ``` 40 | 41 | Com as configurações de desenvolvimento terminadas vamos pular para sintaxe do TypeScript. 42 | 43 | -------------------------------------------------------------------------------- /header.html: -------------------------------------------------------------------------------- 1 | 15 | -------------------------------------------------------------------------------- /images/atomts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overlineink/typescript-book/931d8c2f3adb433808e8ca689687bd24624280f4/images/atomts.png -------------------------------------------------------------------------------- /images/errors/interpreting-errors/ide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overlineink/typescript-book/931d8c2f3adb433808e8ca689687bd24624280f4/images/errors/interpreting-errors/ide.png -------------------------------------------------------------------------------- /images/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overlineink/typescript-book/931d8c2f3adb433808e8ca689687bd24624280f4/images/github.png -------------------------------------------------------------------------------- /images/promise states and fates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overlineink/typescript-book/931d8c2f3adb433808e8ca689687bd24624280f4/images/promise states and fates.png -------------------------------------------------------------------------------- /images/promise states and fates.vsd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overlineink/typescript-book/931d8c2f3adb433808e8ca689687bd24624280f4/images/promise states and fates.vsd -------------------------------------------------------------------------------- /images/venn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overlineink/typescript-book/931d8c2f3adb433808e8ca689687bd24624280f4/images/venn.png -------------------------------------------------------------------------------- /images/venn.vsd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overlineink/typescript-book/931d8c2f3adb433808e8ca689687bd24624280f4/images/venn.vsd -------------------------------------------------------------------------------- /images/venn_pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overlineink/typescript-book/931d8c2f3adb433808e8ca689687bd24624280f4/images/venn_pt.png -------------------------------------------------------------------------------- /intro-1/README.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | 3 | TypeScript can be used with any JavaScript testing framework that you want. In the worst case you can always do a simple `TypeScript -> JavaScript` transform and go your merry way. 4 | 5 | That said, in this section look at options that we have enjoyed greatly 🌹 6 | 7 | -------------------------------------------------------------------------------- /intro-2/README.md: -------------------------------------------------------------------------------- 1 | # Tools 2 | 3 | Here are some great tools that I recommend you use or at least try in your TypeScript projects. 4 | 5 | -------------------------------------------------------------------------------- /intro-2/changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | > Reading a markdown file with the progress in the project is easier than reading a commit log. 4 | 5 | Automatic changelog generation from commit messages is a fairly common pattern nowadays. There is a project called [conventional-changelog](https://github.com/conventional-changelog/conventional-changelog) that generates a changelog from commit messages that follow a _convention_. 6 | 7 | ## Commit message convention 8 | 9 | The most common convention is the _angular_ commit messages convention which is [detailed here](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines). 10 | 11 | ## Setup 12 | 13 | * Install: 14 | 15 | ```bash 16 | npm install standard-version -D 17 | ``` 18 | 19 | * Add a `script` target to your `package.json`: 20 | 21 | ```javascript 22 | { 23 | "scripts": { 24 | "release": "standard-version" 25 | } 26 | } 27 | ``` 28 | 29 | * Optionally : To automatically push the new _git commit and tag_ plus publish to npm add a `postrelease` script: 30 | 31 | ```javascript 32 | { 33 | "scripts": { 34 | "release": "standard-version", 35 | "postrelease": "git push --follow-tags origin master && npm publish" 36 | } 37 | } 38 | ``` 39 | 40 | ## Releasing 41 | 42 | Simply run: 43 | 44 | ```bash 45 | npm run release 46 | ``` 47 | 48 | Based on the commit messages `major` \| `minor` \| `patch` is automatically determined. To _explicitly_ specify a version you can specify `--release-as` e.g.: 49 | 50 | ```bash 51 | npm run release -- --release-as minor 52 | ``` 53 | 54 | -------------------------------------------------------------------------------- /intro-2/husky.md: -------------------------------------------------------------------------------- 1 | # Husky 2 | 3 | > Husky can prevent bad commits, pushes and more 🐶! 4 | 5 | If you want to run some JavaScript / TypeScript code before a commit takes place, husky is the tool for that. 6 | 7 | For example, you can use husky to make sure files are formatted by prettier automatically so you don't have to worry about manually formatting files ever again and focus on the objective of the code instead. Here is the setup: 8 | 9 | * `npm install husky -D` 10 | * Add `scripts` to `package.json`: 11 | 12 | ```text 13 | "precommit": "npm run prettier:write", 14 | ``` 15 | 16 | Now whenever you commit code and there are any formatting changes that need to be made, you'd get them as a _modified_ file in your git log. You can now 17 | 18 | * If you have pushed your code already, simply commit them with a comment `pretty`. 19 | * If you haven't pushed your code, amend your last commit and look like a superhero. 20 | 21 | -------------------------------------------------------------------------------- /intro-2/prettier.md: -------------------------------------------------------------------------------- 1 | # Prettier 2 | 3 | Prettier is a great tool by facebook that makes code formatting so much easier that it's worth mentioning. Setting up with TypeScript using our recommended project setup \(aka everything in `src` folder\) is super easy: 4 | 5 | ## Setup 6 | 7 | * `npm install prettier -D` 8 | * Add `scripts` to `package.json`: 9 | 10 | ```text 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 | ## Usage 17 | 18 | On your build server: 19 | 20 | * `npm run prettier:check` 21 | 22 | During dev \(or pre commit hook\): 23 | 24 | * `npm run prettier:write` 25 | 26 | -------------------------------------------------------------------------------- /intro/README.md: -------------------------------------------------------------------------------- 1 | # Options 2 | 3 | There are a few things that TypeScript prevents you from doing out of the box e.g. using a variable that _isn't ever declared_ \(of course you can use a _declaration file_ for external systems\). 4 | 5 | That said, traditionally programming languages have a hard boundary between what is and isn't allowed by the type system. TypeScript is different in that it gives you control over where you put the slider. This is really to allow you to use the JavaScript you know and love with as much safety as **you** want. There are lots of compiler options to control exactly this slider so let's have a look. 6 | 7 | ## Boolean Options 8 | 9 | `compilerOptions` that are `boolean` can be specified as `compilerOptions` in `tsconfig.json`: 10 | 11 | ```javascript 12 | { 13 | "compilerOptions": { 14 | "someBooleanOption": true 15 | } 16 | } 17 | ``` 18 | 19 | or on the command line 20 | 21 | ```bash 22 | tsc --someBooleanOption 23 | ``` 24 | 25 | > All of these are `false` by default. 26 | 27 | Click [here](https://www.typescriptlang.org/docs/handbook/compiler-options.html) to see all compiler options. 28 | 29 | -------------------------------------------------------------------------------- /intro/noimplicitany.md: -------------------------------------------------------------------------------- 1 | # noImplicitAny 2 | 3 | There are some things that cannot be inferred or inferring them might result in unexpected errors. A fine example is function arguments. If you don't annotate them, its unclear what should and shouldn't be valid e.g. 4 | 5 | ```typescript 6 | function log(someArg) { 7 | sendDataToServer(someArg); 8 | } 9 | 10 | // What arg is valid and what isn't? 11 | log(123); 12 | log('hello world'); 13 | ``` 14 | 15 | So if you don't annotate some function argument, TypeScript assumes `any` and moves on. This essentially turns off type checking for such cases, which is what a JavaScript dev would expect. But this can catch people that want high safety off guard. Hence there is an option, `noImplicitAny`, that when switched on will flag the cases where the type cannot be inferred e.g. 16 | 17 | ```typescript 18 | function log(someArg) { // Error : someArg has an implicit `any` type 19 | sendDataToServer(someArg); 20 | } 21 | ``` 22 | 23 | Of course you can then go ahead and annotate: 24 | 25 | ```typescript 26 | function log(someArg: number) { 27 | sendDataToServer(someArg); 28 | } 29 | ``` 30 | 31 | And if you truly want _zero safety_ you can mark it _explicitly_ as `any`: 32 | 33 | ```typescript 34 | function log(someArg: any) { 35 | sendDataToServer(someArg); 36 | } 37 | ``` 38 | 39 | -------------------------------------------------------------------------------- /main-1/README.md: -------------------------------------------------------------------------------- 1 | # TIPs 2 | 3 | In this section we present a number of tips that we have collected over the course of using TypeScript in the real world. 4 | 5 | -------------------------------------------------------------------------------- /main-1/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 | ```typescript 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 | ```typescript 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 | ```typescript 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 | ```typescript 38 | import { Foo, Bar, Baz } from '../demo'; // demo/index.ts is implied 39 | ``` 40 | 41 | ## Named exports 42 | 43 | Instead of exporting `*`, you can choose to export the module in a name. E.g., assume that `baz.ts` has functions: 44 | 45 | ```typescript 46 | // demo/foo.ts 47 | export class Foo {} 48 | 49 | // demo/bar.ts 50 | export class Bar {} 51 | 52 | // demo/baz.ts 53 | export function getBaz() {} 54 | export function setBaz() {} 55 | ``` 56 | 57 | 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: 58 | 59 | ```typescript 60 | // demo/index.ts 61 | export * from './foo'; // re-export all of its exports 62 | export * from './bar'; // re-export all of its exports 63 | 64 | import * as baz from './baz'; // import as a name 65 | export { baz }; // export the name 66 | ``` 67 | 68 | And now the consumer would look like: 69 | 70 | ```typescript 71 | import { Foo, Bar, baz } from '../demo'; // demo/index.ts is implied 72 | 73 | // usage 74 | baz.getBaz(); 75 | baz.setBaz(); 76 | // etc. ... 77 | ``` 78 | 79 | -------------------------------------------------------------------------------- /main-1/bind.md: -------------------------------------------------------------------------------- 1 | # Bind is Bad 2 | 3 | This is the definition of `bind` in `lib.d.ts`: 4 | 5 | ```typescript 6 | bind(thisArg: any, ...argArray: any[]): any; 7 | ``` 8 | 9 | As you can see it returns **any**! That means that calling `bind` on a function will cause you to completely lose any type safety of the original function signature. 10 | 11 | For example the following compiles: 12 | 13 | ```typescript 14 | function twoParams(a:number,b:number) { 15 | return a + b; 16 | } 17 | let curryOne = twoParams.bind(null,123); 18 | curryOne(456); // Okay but is not type checked! 19 | curryOne('456'); // Allowed because it wasn't type checked! 20 | ``` 21 | 22 | A better way to write it would be with a simple [arrow function](../future-javascript/arrow-functions.md) with an explicit type annotation: 23 | 24 | ```typescript 25 | function twoParams(a:number,b:number) { 26 | return a + b; 27 | } 28 | let curryOne = (x:number)=>twoParams(123,x); 29 | curryOne(456); // Okay and type checked! 30 | curryOne('456'); // Error! 31 | ``` 32 | 33 | But if you expect a curried function [there is a better pattern for that](currying.md). 34 | 35 | ## Class Members 36 | 37 | Another common use is to use `bind` to ensure the correct value of `this` when passing around class functions. Don't do that! 38 | 39 | The following demonstrates the fact that you lose parameter type safety if you use `bind`: 40 | 41 | ```typescript 42 | class Adder { 43 | constructor(public a: string) { } 44 | 45 | add(b: string): string { 46 | return this.a + b; 47 | } 48 | } 49 | 50 | function useAdd(add: (x: number) => number) { 51 | return add(456); 52 | } 53 | 54 | let adder = new Adder('mary had a little 🐑'); 55 | useAdd(adder.add.bind(adder)); // No compile error! 56 | useAdd((x) => adder.add(x)); // Error: number is not assignable to string 57 | ``` 58 | 59 | If you have a class member function that you **expect** to pass around, [use an arrow function in the first place](../future-javascript/arrow-functions.md) e.g one would write the same `Adder` class as: 60 | 61 | ```typescript 62 | class Adder { 63 | constructor(public a: string) { } 64 | 65 | // This function is now safe to pass around 66 | add = (b: string): string => { 67 | return this.a + b; 68 | } 69 | } 70 | ``` 71 | 72 | Another alternative is to _manually_ specify the type of the variable you are binding e.g. 73 | 74 | ```typescript 75 | const add: typeof adder.add = adder.add.bind(adder); 76 | ``` 77 | 78 | -------------------------------------------------------------------------------- /main-1/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 | ```javascript 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 | ```typescript 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 | 50 | -------------------------------------------------------------------------------- /main-1/classesareuseful.md: -------------------------------------------------------------------------------- 1 | # Classes are Useful 2 | 3 | It is very common to have the following structure: 4 | 5 | ```typescript 6 | function foo() { 7 | let someProperty; 8 | 9 | // Some other initialization code 10 | 11 | function someMethod() { 12 | // Do some stuff with `someProperty` 13 | // And potentially other things 14 | } 15 | // Maybe some other methods 16 | 17 | return { 18 | someMethod, 19 | // Maybe some other methods 20 | }; 21 | } 22 | ``` 23 | 24 | This is known as the _revealing module pattern_ and quite common in JavaScript \(taking advantage of JavaScript closure\). 25 | 26 | If you use [_file modules_ \(which you really should as global scope is bad\)](../project/modules/) then _your file is effectively the same_. However, there are too many cases where people will write code like the following: 27 | 28 | ```typescript 29 | let someProperty; 30 | 31 | function foo() { 32 | // Some initialization code 33 | } 34 | foo(); // some initialization code 35 | 36 | someProperty = 123; // some more initialization 37 | 38 | // Some utility function not exported 39 | 40 | // later 41 | export function someMethod() { 42 | 43 | } 44 | ``` 45 | 46 | Even though I am not a big fan of inheritance _I do find that letting people use classes helps them organize their code better_. The same developer would intuitively write the following: 47 | 48 | ```typescript 49 | class Foo { 50 | public someProperty; 51 | 52 | constructor() { 53 | // some initialization 54 | } 55 | 56 | public someMethod() { 57 | // some code 58 | } 59 | 60 | private someUtility() { 61 | // some code 62 | } 63 | } 64 | 65 | export = new Foo(); 66 | ``` 67 | 68 | And its not just developers, creating dev tools that provide great visualizations over classes are much more common, and there is one less pattern your team needs to understand and maintain. 69 | 70 | > PS: There is nothing wrong in my opinion with _shallow_ class hierarchies if they provide significant reuse and reduction in boiler plate. 71 | 72 | -------------------------------------------------------------------------------- /main-1/create-arrays.md: -------------------------------------------------------------------------------- 1 | # Create Arrays 2 | 3 | Creating an empty array is super easy: 4 | 5 | ```typescript 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 | ```typescript 12 | const foo:string[] = new Array(3).fill(''); 13 | console.log(foo); // ['','','']; 14 | ``` 15 | 16 | -------------------------------------------------------------------------------- /main-1/currying.md: -------------------------------------------------------------------------------- 1 | # Currying 2 | 3 | Just use a chain of fat arrow functions: 4 | 5 | ```typescript 6 | // A curried function 7 | let add = (x: number) => (y: number) => x + y; 8 | 9 | // Simple usage 10 | add(123)(456); 11 | 12 | // partially applied 13 | let add123 = add(123); 14 | 15 | // fully apply the function 16 | add123(456); 17 | ``` 18 | 19 | -------------------------------------------------------------------------------- /main-1/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 | ```typescript 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 | ```typescript 18 | function foo(config: {flagA: boolean, flagB: boolean}) { 19 | const {flagA, flagB} = config; 20 | // your awesome function body 21 | } 22 | ``` 23 | 24 | Now the function calls will look like `foo({flagA, flagB})` which makes it much easier to spot mistakes and code review. 25 | 26 | > Note : If your function is simple enough, and you don't expect much churn, then feel free to ignore this advice 🌹. 27 | 28 | -------------------------------------------------------------------------------- /main-1/jquery.md: -------------------------------------------------------------------------------- 1 | # JQuery tips 2 | 3 | Note: you need to install the `jquery.d.ts` file for these tips 4 | 5 | ## Quickly define a new plugin 6 | 7 | Just create `jquery-foo.d.ts` with: 8 | 9 | ```typescript 10 | interface JQuery { 11 | foo: any; 12 | } 13 | ``` 14 | 15 | And now you can use `$('something').foo({whateverYouWant:'hello jquery plugin'})` 16 | 17 | -------------------------------------------------------------------------------- /main-1/lazyobjectliteralinitialization.md: -------------------------------------------------------------------------------- 1 | # Lazy Object Literal Initialization 2 | 3 | Quite commonly in JavaScript code bases you would initialize object literals in the following manner: 4 | 5 | ```typescript 6 | let foo = {}; 7 | foo.bar = 123; 8 | foo.bas = "Hello World"; 9 | ``` 10 | 11 | As soon as you move the code to TypeScript you will start to get Errors like the following: 12 | 13 | ```typescript 14 | let foo = {}; 15 | foo.bar = 123; // Error: Property 'bar' does not exist on type '{}' 16 | foo.bas = "Hello World"; // Error: Property 'bas' does not exist on type '{}' 17 | ``` 18 | 19 | This is because from the state `let foo = {}`, TypeScript _infers_ the type of `foo` \(left hand side of initializing assignment\) to be the type of the right hand side `{}` \(i.e. an object with no properties\). So, it error if you try to assign to a property it doesn't know about. 20 | 21 | ## Ideal Fix 22 | 23 | The _proper_ way to initialize an object in TypeScript is to do it in the assignment: 24 | 25 | ```typescript 26 | let foo = { 27 | bar: 123, 28 | bas: "Hello World", 29 | }; 30 | ``` 31 | 32 | This is also great for code review and code maintainability purposes. 33 | 34 | > The quick fix and middle ground _lazy_ initialization patterns described below suffer from _mistakenly forgetting to initialize a property_. 35 | 36 | ## Quick Fix 37 | 38 | If you have a large JavaScript code base that you are migrating to TypeScript the ideal fix might not be a viable solution for you. In that case you can carefully use a _type assertion_ to silence the compiler: 39 | 40 | ```typescript 41 | let foo = {} as any; 42 | foo.bar = 123; 43 | foo.bas = "Hello World"; 44 | ``` 45 | 46 | ## Middle Ground 47 | 48 | Of course using the `any` assertion can be very bad as it sort of defeats the safety of TypeScript. The middle ground fix is to create an `interface` to ensure 49 | 50 | * Good Docs 51 | * Safe assignment 52 | 53 | This is shown below: 54 | 55 | ```typescript 56 | interface Foo { 57 | bar: number 58 | bas: string 59 | } 60 | 61 | let foo = {} as Foo; 62 | foo.bar = 123; 63 | foo.bas = "Hello World"; 64 | ``` 65 | 66 | Here is a quick example that shows the fact that using the interface can save you: 67 | 68 | ```typescript 69 | interface Foo { 70 | bar: number 71 | bas: string 72 | } 73 | 74 | let foo = {} as Foo; 75 | foo.bar = 123; 76 | foo.bas = "Hello World"; 77 | 78 | // later in the codebase: 79 | foo.bar = 'Hello Stranger'; // Error: You probably misspelled `bas` as `bar`, cannot assign string to number 80 | } 81 | ``` 82 | 83 | -------------------------------------------------------------------------------- /main-1/propertysetters.md: -------------------------------------------------------------------------------- 1 | # Limit Property Setters 2 | 3 | Prefer explicit set/get functions \(e.g. `setBar` and `getBar` functions\) over setters/getters. 4 | 5 | Consider the following code: 6 | 7 | ```typescript 8 | foo.bar = { 9 | a: 123, 10 | b: 456 11 | }; 12 | ``` 13 | 14 | In the presence of setter/getters: 15 | 16 | ```typescript 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 | This is not a _good_ use of property setters. The person reading the first code sample has no context about all the things that will change. Whereas someone calling `foo.setBar(value)` might have an idea that something might change on `foo`. 29 | 30 | > Bonus points: Find references works better if you have different functions. In TypeScript tools if you find references for a getter or a setter you get _both_ whereas with explicit function calls you only get references to the relevant function. 31 | 32 | -------------------------------------------------------------------------------- /main-1/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 | ```typescript 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 | ```typescript 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 | ```typescript 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 | -------------------------------------------------------------------------------- /main-1/statefulfunctions.md: -------------------------------------------------------------------------------- 1 | # Stateful Functions 2 | 3 | A common feature in other programming languages is usage of the `static` keyword to increase the _lifetime_ \(not _scope_\) of a function variable to live beyond function invocations. Here is a `C` sample that achieves this: 4 | 5 | ```c 6 | void called() { 7 | static count = 0; 8 | count++; 9 | printf("Called : %d", count); 10 | } 11 | 12 | int main () { 13 | called(); // Called : 1 14 | called(); // Called : 2 15 | return 0; 16 | } 17 | ``` 18 | 19 | Since JavaScript \(or TypeScript\) doesn't have function statics you can achieve the same thing using various abstractions that wrap over a local variable e.g. using a `class` : 20 | 21 | ```typescript 22 | const {called} = new class { 23 | count = 0; 24 | called = () => { 25 | this.count++; 26 | console.log(`Called : ${this.count}`); 27 | } 28 | }; 29 | 30 | called(); // Called : 1 31 | called(); // Called : 2 32 | ``` 33 | 34 | > C++ developers also try and achieve this using a pattern they call `functor` \(a class that overrides the operator `()`\). 35 | 36 | -------------------------------------------------------------------------------- /main-1/staticconstructor.md: -------------------------------------------------------------------------------- 1 | # static constructors 2 | 3 | TypeScript `class` \(like JavaScript `class`\) cannot have a static constructor. However, you can get the same effect quite easily by just calling it yourself: 4 | 5 | ```typescript 6 | class MyClass { 7 | static initialize() { 8 | // Initialization 9 | } 10 | } 11 | MyClass.initialize(); 12 | ``` 13 | 14 | -------------------------------------------------------------------------------- /main-1/stringenums.md: -------------------------------------------------------------------------------- 1 | # String Based Enums 2 | 3 | Sometimes you need a collection of strings collected under a common key. Prior to TypeScript 2.4, TypeScript only supported number-based enums. If using versions prior to 2.4, a work-around is to use [string literal types to create string based enums by combining with union types](../type-system/literal-types.md). 4 | 5 | -------------------------------------------------------------------------------- /main-1/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 | ```typescript 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 | 15 | Essentially `EventEmitter` internally stores data in the form of mapped arrays: 16 | 17 | ```typescript 18 | {foo: [fooListeners], bar: [barListeners]} 19 | ``` 20 | 21 | Instead, for the sake of _event_ type safety, you can create an emitter _per_ event type: 22 | 23 | ```typescript 24 | const onFoo = new TypedEvent(); 25 | const onBar = new TypedEvent(); 26 | 27 | // Emit: 28 | onFoo.emit(foo); 29 | onBar.emit(bar); 30 | // Listen: 31 | onFoo.on((foo)=>console.log(foo)); 32 | onBar.on((bar)=>console.log(bar)); 33 | ``` 34 | 35 | This has the following advantages: 36 | 37 | * The types of events are easily discoverable as variables. 38 | * The event emitter variables are easily refactored independently. 39 | * Type safety for event data structures. 40 | 41 | ## Reference TypedEvent 42 | 43 | ```typescript 44 | export interface Listener { 45 | (event: T): any; 46 | } 47 | 48 | export interface Disposable { 49 | dispose(); 50 | } 51 | 52 | /** passes through events as they happen. You will not get events from before you start listening */ 53 | export class TypedEvent { 54 | private listeners: Listener[] = []; 55 | private listenersOncer: Listener[] = []; 56 | 57 | on = (listener: Listener): Disposable => { 58 | this.listeners.push(listener); 59 | return { 60 | dispose: () => this.off(listener) 61 | }; 62 | } 63 | 64 | once = (listener: Listener): void => { 65 | this.listenersOncer.push(listener); 66 | } 67 | 68 | off = (listener: Listener) => { 69 | var callbackIndex = this.listeners.indexOf(listener); 70 | if (callbackIndex > -1) this.listeners.splice(callbackIndex, 1); 71 | } 72 | 73 | emit = (event: T) => { 74 | /** Update any general listeners */ 75 | this.listeners.forEach((listener) => listener(event)); 76 | 77 | /** Clear the `once` queue */ 78 | this.listenersOncer.forEach((listener) => listener(event)); 79 | this.listenersOncer = []; 80 | } 81 | 82 | pipe = (te: TypedEvent): Disposable => { 83 | return this.on((e) => te.emit(e)); 84 | } 85 | } 86 | ``` 87 | 88 | -------------------------------------------------------------------------------- /main-1/typeinstantiation.md: -------------------------------------------------------------------------------- 1 | # Type Instantiation 2 | 3 | Say you have something that has a generic parameter e.g. a class `Foo`: 4 | 5 | ```typescript 6 | class Foo{ 7 | foo: T; 8 | } 9 | ``` 10 | 11 | You want to create a specialized version for it for a particular type. The pattern is to copy the item into a new variable and give it the type annotation with the generics replaced with concrete types. E.g. if you want a class `Foo`: 12 | 13 | ```typescript 14 | class Foo{ 15 | foo: T; 16 | } 17 | let FooNumber = Foo as { new ():Foo }; // ref 1 18 | ``` 19 | 20 | In `ref 1` you are saying that `FooNumber` is the same as `Foo` but just treat it as something that when called with the `new` operator gives an instance of `Foo`. 21 | 22 | ## Inheritance 23 | 24 | The Type assertion pattern is unsafe in that it trusts you to do the right thing. A common pattern in other languages _for classes_ is to just use inheritance : 25 | 26 | ```typescript 27 | class FooNumber extends Foo{} 28 | ``` 29 | 30 | One word of caution here: if you use decorators on the base class then the inherited class might not have the same behavior as the base class \(it is no longer wrapped by the decorator\). 31 | 32 | Of course if you are not specializing classes you still have to come up with a coercion / assertion pattern that works and hence we showed the general assertion pattern first, e.g.: 33 | 34 | ```typescript 35 | function id(x: T) { return x; } 36 | const idNum = id as {(x:number):number}; 37 | ``` 38 | 39 | > Inspired by this [stackoverflow question](http://stackoverflow.com/a/34864705/390330) 40 | 41 | -------------------------------------------------------------------------------- /main/README.md: -------------------------------------------------------------------------------- 1 | # Errors in TypeScript 2 | 3 | In this section we discuss how to read and understand TypeScript errors. We follow this with common errors and their solutions. 4 | 5 | -------------------------------------------------------------------------------- /main/common-errors.md: -------------------------------------------------------------------------------- 1 | # Common Errors 2 | 3 | In this section we explain a number of common error codes that users experience in the real world. 4 | 5 | ## TS2304 6 | 7 | Samples: 8 | 9 | > `Cannot find name ga` `Cannot find name $` `Cannot find module jquery` 10 | 11 | You are probably using a third party library \(e.g. google analytics\) and don't have it `declare`d. TypeScript tries to save you from _spelling mistakes_ and _using variables without declaring them_ so you need to be explicit on anything that is _available at runtime_ because of you including some external library \([more on how to fix it](../type-system/intro/d.ts.md)\). 12 | 13 | ## TS2307 14 | 15 | Samples: 16 | 17 | > `Cannot find module 'underscore'` 18 | 19 | You are probably using a third party library \(e.g. underscore\) as a _module_ \([more on modules](../project/modules/)\) and don't have the ambient declaration file for it \([more on ambient declarations](../type-system/intro/d.ts.md)\). 20 | 21 | ## TS1148 22 | 23 | Sample: 24 | 25 | > Cannot compile modules unless the '--module' flag is provided 26 | 27 | Checkout the [section on modules](../project/modules/). 28 | 29 | ## Catch clause variable cannot have a type annotation 30 | 31 | Sample: 32 | 33 | ```javascript 34 | try { something(); } 35 | catch (e: Error) { // Catch clause variable cannot have a type annotation 36 | } 37 | ``` 38 | 39 | TypeScript is protecting you from JavaScript code in the wild being wrong. Use a type guard instead: 40 | 41 | ```javascript 42 | try { something(); } 43 | catch (e) { 44 | if (e instanceof Error){ 45 | // Here you go. 46 | } 47 | } 48 | ``` 49 | 50 | ## Interface `ElementClass` cannot simultaneously extend types `Component` and `Component` 51 | 52 | This happens when you have two `react.d.ts` \(`@types/react/index.d.ts`\) in the compilation context. 53 | 54 | **Fix**: 55 | 56 | * Delete `node_modules` and any `package-lock` \(or yarn lock\) and `npm install` again. 57 | * If it doesn't work, find the invalid module \(all modules used by your project should have `react.d.ts` as a `peerDependency` and not a hard `dependency`\) and report it on their project. 58 | 59 | -------------------------------------------------------------------------------- /overview/ast/README.md: -------------------------------------------------------------------------------- 1 | # AST 2 | 3 | ## Node 4 | 5 | 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. 6 | 7 | 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. 8 | 9 | Here are a few key `interface Node` members: 10 | 11 | * `TextRange` members that identify the node's `start` and `end` in the source file. 12 | * `parent?: Node` the parent of the node in the AST. 13 | 14 | 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. 15 | 16 | ## SourceFile 17 | 18 | * `SyntaxKind.SourceFile` 19 | * `interface SourceFile`. 20 | 21 | Each `SourceFile` is a top-level AST node that is contained in the `Program`. 22 | 23 | -------------------------------------------------------------------------------- /overview/ast/ast-tip-children.md: -------------------------------------------------------------------------------- 1 | # 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 | ```typescript 8 | export function forEachChild(node: Node, cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T { 9 | if (!node) { 10 | return; 11 | } 12 | switch (node.kind) { 13 | case SyntaxKind.BinaryExpression: 14 | return visitNode(cbNode, (node).left) || 15 | visitNode(cbNode, (node).operatorToken) || 16 | visitNode(cbNode, (node).right); 17 | case SyntaxKind.IfStatement: 18 | return visitNode(cbNode, (node).expression) || 19 | visitNode(cbNode, (node).thenStatement) || 20 | visitNode(cbNode, (node).elseStatement); 21 | 22 | // .... lots more 23 | ``` 24 | 25 | 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`. 26 | 27 | E.g. here is a function that prints the verbose `AST` of a node: 28 | 29 | ```typescript 30 | function printAllChildren(node: ts.Node, depth = 0) { 31 | console.log(new Array(depth+1).join('----'), ts.syntaxKindToName(node.kind), node.pos, node.end); 32 | depth++; 33 | node.getChildren().forEach(c=> printAllChildren(c, depth)); 34 | } 35 | ``` 36 | 37 | We will see a sample usage of this function when we discuss the parser further. 38 | 39 | -------------------------------------------------------------------------------- /overview/ast/ast-tip-syntaxkind.md: -------------------------------------------------------------------------------- 1 | # TIP: SyntaxKind enum 2 | 3 | `SyntaxKind` is defined as a `const enum`, here is a sample: 4 | 5 | ```typescript 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](../../type-system/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 | ```typescript 16 | export function syntaxKindToName(kind: ts.SyntaxKind) { 17 | return (ts).SyntaxKind[kind]; 18 | } 19 | ``` 20 | 21 | -------------------------------------------------------------------------------- /overview/ast/ast-trivia.md: -------------------------------------------------------------------------------- 1 | # Trivia 2 | 3 | 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. 4 | 5 | Before we show them you need to understand the following: 6 | 7 | ## Trivia Ownership 8 | 9 | In General: 10 | 11 | * A token owns any trivia after it on the _same_ line _upto_ the next token. 12 | * Any comment _after that line_ is associated with the following token. 13 | 14 | For leading and ending comments in a file: 15 | 16 | * The first token in the source file gets all the initial trivia. 17 | * The last sequence of trivia in the file is tacked onto the end-of-file token, which otherwise has zero width. 18 | 19 | ## Trivia APIs 20 | 21 | For most basic uses, comments are the "interesting" trivia. The comments that belong to a Node can be fetched through the following functions: 22 | 23 | | Function | Description | 24 | | :--- | :--- | 25 | | `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`\). | 26 | | `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`\). | 27 | 28 | As an example, imagine this portion of a source file: 29 | 30 | ```typescript 31 | debugger;/*hello*/ 32 | //bye 33 | /*hi*/ function 34 | ``` 35 | 36 | `getLeadingCommentRanges` for the `function` will only return the last 2 comments `//bye` and `/*hi*/`. 37 | 38 | Appropriately, calling `getTrailingCommentRanges` on the end of the debugger statement will extract the `/*hello*/` comment. 39 | 40 | ## Token Start/Full Start 41 | 42 | Nodes have what is called a "token start" and a "full start". 43 | 44 | * Token Start: the more natural version, which is the position in file where the text of a token begins 45 | * Full Start: the point at which the scanner began scanning since the last significant token 46 | 47 | AST nodes have an API for `getStart` and `getFullStart`. In the following example: 48 | 49 | ```typescript 50 | debugger;/*hello*/ 51 | //bye 52 | /*hi*/ function 53 | ``` 54 | 55 | 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. 56 | 57 | -------------------------------------------------------------------------------- /overview/binder/README.md: -------------------------------------------------------------------------------- 1 | # Binder 2 | 3 | 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: 4 | 5 | ```typescript 6 | SourceCode ~~Scanner~~> Tokens ~~Parser~~> AST ~~Emitter~~> JavaScript 7 | ``` 8 | 9 | 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_. 10 | 11 | ## Symbol 12 | 13 | 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: 14 | 15 | ```typescript 16 | function Symbol(flags: SymbolFlags, name: string) { 17 | this.flags = flags; 18 | this.name = name; 19 | this.declarations = undefined; 20 | } 21 | ``` 22 | 23 | `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\) 24 | 25 | ## Usage by Checker 26 | 27 | The `binder` is actually used internally by the type `checker` which in turn is used by the `program`. The simplified call stack looks like: 28 | 29 | ```text 30 | program.getTypeChecker -> 31 | ts.createTypeChecker (in checker)-> 32 | initializeTypeChecker (in checker) -> 33 | for each SourceFile `ts.bindSourceFile` (in binder) 34 | // followed by 35 | for each SourceFile `ts.mergeSymbolTable` (in checker) 36 | ``` 37 | 38 | The unit of work for the binder is a SourceFile. The `binder.ts` is driven by `checker.ts`. 39 | 40 | -------------------------------------------------------------------------------- /overview/binder/binder-declarations.md: -------------------------------------------------------------------------------- 1 | # Binder Declarations 2 | 3 | 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 4 | 5 | Note : the `Symbol` for an external module source file is setup as `flags : SymbolFlags.ValueModule` and `name: '"' + removeFileExtension(file.fileName) + '"'`\). 6 | 7 | ```typescript 8 | function addDeclarationToSymbol(symbol: Symbol, node: Declaration, symbolFlags: SymbolFlags) { 9 | symbol.flags |= symbolFlags; 10 | 11 | node.symbol = symbol; 12 | 13 | if (!symbol.declarations) { 14 | symbol.declarations = []; 15 | } 16 | symbol.declarations.push(node); 17 | 18 | if (symbolFlags & SymbolFlags.HasExports && !symbol.exports) { 19 | symbol.exports = {}; 20 | } 21 | 22 | if (symbolFlags & SymbolFlags.HasMembers && !symbol.members) { 23 | symbol.members = {}; 24 | } 25 | 26 | if (symbolFlags & SymbolFlags.Value && !symbol.valueDeclaration) { 27 | symbol.valueDeclaration = node; 28 | } 29 | } 30 | ``` 31 | 32 | The important linking portions: 33 | 34 | * Creates a link to the Symbol from the AST node \(`node.symbol`\). 35 | * Adds the node as _one of_ the declarations of the Symbol \(`symbol.declarations`\). 36 | 37 | ## Declaration 38 | 39 | Declaration is just a `node` with an optional name. In `types.ts` 40 | 41 | ```typescript 42 | interface Declaration extends Node { 43 | _declarationBrand: any; 44 | name?: DeclarationName; 45 | } 46 | ``` 47 | 48 | -------------------------------------------------------------------------------- /overview/binder/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 | ```typescript 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 | 41 | -------------------------------------------------------------------------------- /overview/binder/binder-functions.md: -------------------------------------------------------------------------------- 1 | # Binder Functions 2 | 3 | Two critical binder functions are `bindSourceFile` and `mergeSymbolTable`. We will take a look at these next. 4 | 5 | ## `bindSourceFile` 6 | 7 | Basically checks if `file.locals` is defined, if not it hands over to \(a local function\) `bind`. 8 | 9 | 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\). 10 | 11 | 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`. 12 | 13 | ## `bind` 14 | 15 | 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. 16 | 17 | ## `bindWorker` 18 | 19 | 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` 20 | 21 | ## `bindFoo` functions 22 | 23 | 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: 24 | 25 | ```typescript 26 | function createSymbol(flags: SymbolFlags, name: string): Symbol { 27 | symbolCount++; 28 | return new Symbol(flags, name); 29 | } 30 | ``` 31 | 32 | 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. 33 | 34 | -------------------------------------------------------------------------------- /overview/checker/README.md: -------------------------------------------------------------------------------- 1 | # Checker 2 | 3 | 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\). 4 | 5 | ## Usage by Program 6 | 7 | The `checker` is initialized by `program`. The following is a sampling of the call stack \(we showed the same one when looking at `binder`\): 8 | 9 | ```text 10 | program.getTypeChecker -> 11 | ts.createTypeChecker (in checker)-> 12 | initializeTypeChecker (in checker) -> 13 | for each SourceFile `ts.bindSourceFile` (in binder) 14 | // followed by 15 | for each SourceFile `ts.mergeSymbolTable` (in checker) 16 | ``` 17 | 18 | ## Association with Emitter 19 | 20 | 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. 21 | 22 | Here is the call stack right down to `checkSourceFile` \(a function local to `createTypeChecker`\). 23 | 24 | ```text 25 | program.emit -> 26 | emitWorker (program local) -> 27 | createTypeChecker.getEmitResolver -> 28 | // First call the following functions local to createTypeChecker 29 | call getDiagnostics -> 30 | getDiagnosticsWorker -> 31 | checkSourceFile 32 | 33 | // then 34 | return resolver 35 | (already initialized in createTypeChecker using a call to local createResolver()) 36 | ``` 37 | 38 | -------------------------------------------------------------------------------- /overview/checker/checker-diagnostics.md: -------------------------------------------------------------------------------- 1 | # Checker Error Reporting 2 | 3 | The checker uses the local `error` function to report errors. Here is the function: 4 | 5 | ```typescript 6 | function error(location: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): void { 7 | let diagnostic = location 8 | ? createDiagnosticForNode(location, message, arg0, arg1, arg2) 9 | : createCompilerDiagnostic(message, arg0, arg1, arg2); 10 | diagnostics.add(diagnostic); 11 | } 12 | ``` 13 | 14 | -------------------------------------------------------------------------------- /overview/checker/checker-global.md: -------------------------------------------------------------------------------- 1 | # Checker Diagnostics 2 | 3 | Within `initializeTypeChecker` the following code exists: 4 | 5 | ```typescript 6 | // Initialize global symbol table 7 | forEach(host.getSourceFiles(), file => { 8 | if (!isExternalModule(file)) { 9 | mergeSymbolTable(globals, file.locals); 10 | } 11 | }); 12 | ``` 13 | 14 | Which basically merges all the `global` symbols into the `let globals: SymbolTable = {};` \(in `createTypeChecker`\) SymbolTable. `mergeSymbolTable` primarily calls `mergeSymbol`. 15 | 16 | -------------------------------------------------------------------------------- /overview/emitter/README.md: -------------------------------------------------------------------------------- 1 | # Emitter 2 | 3 | There are two `emitters` provided with the TypeScript compiler: 4 | 5 | * `emitter.ts`: this is the emitter you are most likely to be interested in. Its the TS -> JavaScript emitter. 6 | * `declarationEmitter.ts`: this is the emitter used to create a _declaration file_ \(a `.d.ts`\) for a _TypeScript source file_ \(a `.ts` file\). 7 | 8 | We will look at `emitter.ts` in this section. 9 | 10 | ## Usage by `program` 11 | 12 | Program provides an `emit` function. This function primarily delegates to `emitFiles` function in `emitter.ts`. Here is the call stack: 13 | 14 | ```text 15 | Program.emit -> 16 | `emitWorker` (local in program.ts createProgram) -> 17 | `emitFiles` (function in emitter.ts) 18 | ``` 19 | 20 | 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`. 21 | 22 | -------------------------------------------------------------------------------- /overview/program.md: -------------------------------------------------------------------------------- 1 | # Program 2 | 3 | Defined in `program.ts`. The compilation context \([a concept we covered previously](../project/compilation-context/)\) is represented within the TypeScript compiler as a `Program`. It consists of `SourceFile`s and compiler options. 4 | 5 | ## Usage of `CompilerHost` 6 | 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 | 19 | -------------------------------------------------------------------------------- /project/README.md: -------------------------------------------------------------------------------- 1 | # Project 2 | 3 | To create a successful project using TypeScript you need to understand the various project organization language features available. In this section we will cover "compilation context", declaration spaces and modules. 4 | 5 | -------------------------------------------------------------------------------- /project/compilation-context/README.md: -------------------------------------------------------------------------------- 1 | # Compilation Context 2 | 3 | The compilation context is basically just a fancy term for grouping of the files that TypeScript will parse and analyze to determine what is valid and what isn't. Along with the information about which files, the compilation context contains information about _which compiler options_ are in use. A great way to define this logical grouping \(we also like to use the term _project_\) is using a `tsconfig.json` file. 4 | 5 | -------------------------------------------------------------------------------- /project/compilation-context/files.md: -------------------------------------------------------------------------------- 1 | # Which Files? 2 | 3 | You can either use `files` to be explicit: 4 | 5 | ```javascript 6 | { 7 | "files":[ 8 | "./some/file.ts" 9 | ] 10 | } 11 | ``` 12 | 13 | or `include` and `exclude` to specify files / folders / globs. E.g.: 14 | 15 | ```javascript 16 | { 17 | "include":[ 18 | "./folder" 19 | ], 20 | "exclude":[ 21 | "./folder/**/*.spec.ts", 22 | "./folder/someSubFolder" 23 | ] 24 | } 25 | ``` 26 | 27 | Some notes: 28 | 29 | * For globs : `**/*` \(e.g. sample usage `somefolder/**/*`\) means all folder and any files \(the extensions `.ts`/`.tsx` will be assumed and if `allowJs:true` so will `.js`/`.jsx`\) 30 | 31 | -------------------------------------------------------------------------------- /project/declarationspaces.md: -------------------------------------------------------------------------------- 1 | # Declaration Spaces 2 | 3 | There are two declaration spaces in TypeScript: the _variable_ declaration space and the _type_ declaration space. These concepts are explored below. 4 | 5 | ## Type Declaration Space 6 | 7 | The type declaration space contains stuff that can be used as a type annotation. E.g. the following are a few type declarations: 8 | 9 | ```typescript 10 | class Foo {}; 11 | interface Bar {}; 12 | type Bas = {}; 13 | ``` 14 | 15 | This means that you can use `Foo`, `Bar`, `Bas`, etc. as a type annotation. E.g.: 16 | 17 | ```typescript 18 | var foo: Foo; 19 | var bar: Bar; 20 | var bas: Bas; 21 | ``` 22 | 23 | Notice that even though you have `interface Bar`, _you can't use it as a variable_ because it doesn't contribute to the _variable declaration space_. This is shown below: 24 | 25 | ```typescript 26 | interface Bar {}; 27 | var bar = Bar; // ERROR: "cannot find name 'Bar'" 28 | ``` 29 | 30 | The reason why it says `cannot find name` is because the name `Bar` _is not defined_ in the _variable_ declaration space. That brings us to the next topic "Variable Declaration Space". 31 | 32 | ## Variable Declaration Space 33 | 34 | The variable declaration space contains stuff that you can use as a variable. We saw that having `class Foo` contributes a type `Foo` to the _type_ declaration space. Guess what? it also contributes a _variable_ `Foo` to the _variable_ declaration space as shown below: 35 | 36 | ```typescript 37 | class Foo {}; 38 | var someVar = Foo; 39 | var someOtherVar = 123; 40 | ``` 41 | 42 | This is great as sometimes you want to pass classes around as variables. Remember that: 43 | 44 | * we couldn't use something like an `interface` that is _only_ in the _type_ declaration space as a variable. 45 | 46 | Similarly something that you declare with `var`, is _only_ in the _variable_ declaration space and cannot be used as a type annotation: 47 | 48 | ```typescript 49 | var foo = 123; 50 | var bar: foo; // ERROR: "cannot find name 'foo'" 51 | ``` 52 | 53 | The reason why it says `cannot find name` is because the name `foo` _is not defined_ in the _type_ declaration space. 54 | 55 | -------------------------------------------------------------------------------- /project/modules/README.md: -------------------------------------------------------------------------------- 1 | # Modules 2 | 3 | ## Global Module 4 | 5 | By default when you start typing code in a new TypeScript file your code is in a _global_ namespace. As a demo consider a file `foo.ts`: 6 | 7 | ```typescript 8 | var foo = 123; 9 | ``` 10 | 11 | If you now create a _new_ file `bar.ts` in the same project, you will be _allowed_ by the TypeScript type system to use the variable `foo` as if it was available globally: 12 | 13 | ```typescript 14 | var bar = foo; // allowed 15 | ``` 16 | 17 | Needless to say having a global namespace is dangerous as it opens your code up for naming conflicts. We recommend using file modules which are presented next. 18 | 19 | ## File Module 20 | 21 | Also called _external modules_. If you have an `import` or an `export` at the root level of a TypeScript file then it creates a _local_ scope within that file. So if we were to change the previous `foo.ts` to the following \(note the `export` usage\): 22 | 23 | ```typescript 24 | export var foo = 123; 25 | ``` 26 | 27 | We will no longer have `foo` in the global namespace. This can be demonstrated by creating a new file `bar.ts` as follows: 28 | 29 | ```typescript 30 | var bar = foo; // ERROR: "cannot find name 'foo'" 31 | ``` 32 | 33 | If you want to use stuff from `foo.ts` in `bar.ts` _you need to explicitly import it_. This is shown in an updated `bar.ts` below: 34 | 35 | ```typescript 36 | import { foo } from "./foo"; 37 | var bar = foo; // allowed 38 | ``` 39 | 40 | Using an `import` in `bar.ts` not only allows you to bring in stuff from other files, but also marks the file `bar.ts` as a _module_ and therefore, declarations in `bar.ts` don't pollute the global namespace either. 41 | 42 | What JavaScript is generated from a given TypeScript file that uses external modules is driven by the compiler flag called `module`. 43 | 44 | -------------------------------------------------------------------------------- /project/modules/globals.md: -------------------------------------------------------------------------------- 1 | # globals.d.ts 2 | 3 | We discussed _global_ vs. _file_ modules when covering [projects](./) and recommended using file based modules and not polluting the global namespace. 4 | 5 | Nevertheless, if you have beginning TypeScript developers you can give them a `globals.d.ts` file to put interfaces / types in the global namespace to make it easy to have some _types_ just _magically_ available for consumption in _all_ your TypeScript code. 6 | 7 | > For any code that is going to generate _JavaScript_ we highly recommend using _file modules_. 8 | 9 | * `globals.d.ts` is great for adding extensions to `lib.d.ts` if you need to. 10 | * It's good for quick `declare module "some-library-you-dont-care-to-get-defs-for";` when doing TS to JS migrations. 11 | 12 | -------------------------------------------------------------------------------- /project/namespaces.md: -------------------------------------------------------------------------------- 1 | # Namespaces 2 | 3 | Namespaces provide you with a convenient syntax around a common pattern used in JavaScript: 4 | 5 | ```typescript 6 | (function(something) { 7 | 8 | something.foo = 123; 9 | 10 | })(something || (something = {})) 11 | ``` 12 | 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\). This means that you can have two such blocks split by some execution boundary: 14 | 15 | ```typescript 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 | This is commonly used in the JavaScript land for making sure that stuff doesn't leak into the global namespace. With file based modules you don't need to worry about this, but the pattern is still useful for _logical grouping_ of a bunch of functions. Therefore TypeScript provides the `namespace` keyword to group these e.g.: 34 | 35 | ```typescript 36 | namespace Utility { 37 | export function log(msg) { 38 | console.log(msg); 39 | } 40 | export function error(msg) { 41 | console.error(msg); 42 | } 43 | } 44 | 45 | // usage 46 | Utility.log('Call me'); 47 | Utility.error('maybe!'); 48 | ``` 49 | 50 | The `namespace` keyword generates the same JavaScript that we saw earlier: 51 | 52 | ```typescript 53 | (function (Utility) { 54 | 55 | // Add stuff to Utility 56 | 57 | })(Utility || (Utility = {})); 58 | ``` 59 | 60 | One thing to note is that namespaces can be nested so you can do stuff like `namespace Utility.Messaging` to nest a `Messaging` namespace under `Utility`. 61 | 62 | For most projects we recommend using external modules and using `namespace` for quick demos and porting old JavaScript code. 63 | 64 | -------------------------------------------------------------------------------- /recap/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript 2 | 3 | Havia \(e continuará a ter\) muitos competidores em _alguns compiladores de sintaxe_ para o _JavaScript_. TypeScript é diferente deles isso por que o _Seu JavaScript é o TypeScript_. Aqui está um diagrama: 4 | 5 | ![Seu JavaScript é o TypeScript](https://raw.githubusercontent.com/overlineink/typescript-book/master/images/venn_pt.png) 6 | 7 | No entanto, isso significa que _você só precisa conhecer JavaScript_ \(a boa notícia é _você **apenas** precisa aprender JavaScript_\). O TypeScript está apenas padronizando todas as maneiras que você fornece _uma boa documentação_ em JavaScript. 8 | 9 | * Apenas dando-lhe uma nova sintaxe não ajuda a corrigir bugs \(olhando para você CoffeeScript\). 10 | * Criando uma nova linguagem abstrai você muito longe de seus tempos de execução, comunidades \(olhando para você Dart\). 11 | 12 | O TypeScript é apenas um JavaScript documentado. 13 | 14 | ## Tornando o JavaScript melhor 15 | 16 | O TypeScript tentará protegê-lo de partes do JavaScript que nunca funcionaram \(então você não precisa se lembrar disso\): 17 | 18 | ```typescript 19 | [] + []; // JavaScript vai te dar "" (o que faz pouco sentido), TypeScript vai reportar um erro 20 | 21 | // 22 | // outras coisas que são sem sentido no JavaScript 23 | // - não lhe dão um erro de execução (dificultando a depuração) 24 | // - mas o TypeScript lhe dará um erro em tempo de compilação (tornando a depuração desnecessária) 25 | // 26 | {} + []; // JS : 0, TS Erro 27 | [] + {}; // JS : "[object Object]", TS Erro 28 | {} + {}; // JS : NaN ou [object Object][object Object] dependendo do navegador, TS Erro 29 | "hello" - 1; // JS : NaN, TS Erro 30 | 31 | function add(a,b) { 32 | return 33 | a + b; // JS : undefined, TS Erro 'código inacessível detectado' 34 | } 35 | ``` 36 | 37 | Essencialmente TypeScript faz lint dos erros do JavaScript. Apenas fazendo um trabalho melhor do que outros linters que não possuem _tipo de informações_. 38 | 39 | ## Você ainda precisa aprender JavaScript 40 | 41 | Dito isso, o TypeScript é muito pragmático sobre o fato de que _você escreve JavaScript_, portanto, há algumas coisas sobre JavaScript que você ainda precisa saber para não ser pego de surpresa. Vamos discuti-los em seguida. 42 | 43 | > Nota: O TypeScript é um superconjunto do JavaScript. Apenas com documentação que pode realmente ser usada por compiladores / IDEs ;\) 44 | 45 | -------------------------------------------------------------------------------- /recap/closure.md: -------------------------------------------------------------------------------- 1 | # Closure 2 | 3 | The best thing that JavaScript ever got was closures. A function in JavaScript has access to any variables defined in the outer scope. Closures are best explained with examples: 4 | 5 | ```typescript 6 | function outerFunction(arg) { 7 | var variableInOuterFunction = arg; 8 | 9 | function bar() { 10 | console.log(variableInOuterFunction); // Access a variable from the outer scope 11 | } 12 | 13 | // Call the local function to demonstrate that it has access to arg 14 | bar(); 15 | } 16 | 17 | outerFunction("hello closure"); // logs hello closure! 18 | ``` 19 | 20 | You can see that the inner function has access to a variable \(variableInOuterFunction\) from the outer scope. The variables in the outer function have been closed by \(or bound in\) the inner function. Hence the term **closure**. The concept in itself is simple enough and pretty intuitive. 21 | 22 | Now the awesome part: The inner function can access the variables from the outer scope _even after the outer function has returned_. This is because the variables are still bound in the inner function and not dependent on the outer function. Again let's look at an example: 23 | 24 | ```typescript 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 | // Note the outerFunction has returned 35 | innerFunction(); // logs hello closure! 36 | ``` 37 | 38 | ## Reason why it's awesome 39 | 40 | It allows you to compose objects easily e.g. the revealing module pattern: 41 | 42 | ```typescript 43 | function createCounter() { 44 | let val = 0; 45 | return { 46 | increment() { val++ }, 47 | getVal() { return val } 48 | } 49 | } 50 | 51 | let counter = createCounter(); 52 | counter.increment(); 53 | console.log(counter.getVal()); // 1 54 | counter.increment(); 55 | console.log(counter.getVal()); // 2 56 | ``` 57 | 58 | At a high level it is also what makes something like Node.js possible \(don't worry if it doesn't click in your brain right now. It will eventually 🌹\): 59 | 60 | ```typescript 61 | // Pseudo code to explain the concept 62 | server.on(function handler(req, res) { 63 | loadData(req.id).then(function(data) { 64 | // the `res` has been closed over and is available 65 | res.send(data); 66 | }) 67 | }); 68 | ``` 69 | 70 | -------------------------------------------------------------------------------- /recap/equality.md: -------------------------------------------------------------------------------- 1 | # Igualdade 2 | 3 | ## Equality 4 | 5 | One thing to be careful about in JavaScript is the difference between `==` and `===`. As JavaScript tries to be resilient against programming errors `==` tries to do type coercion between two variables e.g. converts a string to a number so that you can compare with a number as shown below: 6 | 7 | ```javascript 8 | console.log(5 == "5"); // true , TS Error 9 | console.log(5 === "5"); // false , TS Error 10 | ``` 11 | 12 | However, the choices JavaScript makes are not always ideal. For example, in the below example the first statement is false because `""` and `"0"` are both strings and are clearly not equal. However, in the second case both `0` and the empty string \(`""`\) are falsy \(i.e. behave like `false`\) and are therefore equal with respect to `==`. Both statements are false when you use `===`. 13 | 14 | ```javascript 15 | console.log("" == "0"); // false 16 | console.log(0 == ""); // true 17 | 18 | console.log("" === "0"); // false 19 | console.log(0 === ""); // false 20 | ``` 21 | 22 | > Note that `string == number` and `string === number` are both compile time errors in TypeScript, so you don't normally need to worry about this. 23 | 24 | Similar to `==` vs. `===`, there is `!=` vs. `!==` 25 | 26 | So ProTip: Always use `===` and `!==` except for null checks, which we cover later. 27 | 28 | ## Structural Equality 29 | 30 | If you want to compare two objects for structural equality `==`/`===` are _**not**_ sufficient. e.g. 31 | 32 | ```javascript 33 | console.log({a:123} == {a:123}); // False 34 | console.log({a:123} === {a:123}); // False 35 | ``` 36 | 37 | To do such checks use the [deep-equal](https://www.npmjs.com/package/deep-equal) npm package e.g. 38 | 39 | ```javascript 40 | import * as deepEqual from "deep-equal"; 41 | 42 | console.log(deepEqual({a:123},{a:123})); // True 43 | ``` 44 | 45 | However, quite commonly you don't need deep checks and all you really need is to check by some `id` e.g. 46 | 47 | ```typescript 48 | type IdDisplay = { 49 | id: string, 50 | display: string 51 | } 52 | const list: IdDisplay[] = [ 53 | { 54 | id: 'foo', 55 | display: 'Foo Select' 56 | }, 57 | { 58 | id: 'bar', 59 | display: 'Bar Select' 60 | }, 61 | ] 62 | 63 | const fooIndex = list.map(i => i.id).indexOf('foo'); 64 | console.log(fooIndex); // 0 65 | ``` 66 | 67 | -------------------------------------------------------------------------------- /recap/references.md: -------------------------------------------------------------------------------- 1 | # Referências 2 | 3 | Beyond literals, any Object in JavaScript \(including functions, arrays, regexp etc\) are references. This means the following 4 | 5 | ## Mutations are across all references 6 | 7 | ```javascript 8 | var foo = {}; 9 | var bar = foo; // bar is a reference to the same object 10 | 11 | foo.baz = 123; 12 | console.log(bar.baz); // 123 13 | ``` 14 | 15 | ## Equality is for references 16 | 17 | ```javascript 18 | var foo = {}; 19 | var bar = foo; // bar is a reference 20 | var baz = {}; // baz is a *new object* distinct from `foo` 21 | 22 | console.log(foo === bar); // true 23 | console.log(foo === baz); // false 24 | ``` 25 | 26 | -------------------------------------------------------------------------------- /recap/this.md: -------------------------------------------------------------------------------- 1 | # this 2 | 3 | Any access to `this` keyword within a function is actually controlled by how the function is actually called. It is commonly referred to as the “calling context.” 4 | 5 | Here is an example: 6 | 7 | ```typescript 8 | function foo() { 9 | console.log(this); 10 | } 11 | 12 | foo(); // logs out the global e.g. `window` in browsers 13 | let bar = { 14 | foo 15 | } 16 | bar.foo(); // Logs out `bar` as `foo` was called on `bar` 17 | ``` 18 | 19 | So be mindful of your usage of `this`. If you want to disconnect `this` in a class from the calling context use an arrow function, [more on that later](../future-javascript/arrow-functions.md). 20 | 21 | -------------------------------------------------------------------------------- /recap/truthy.md: -------------------------------------------------------------------------------- 1 | # Truthy 2 | 3 | JavaScript has a concept of `truthy` i.e. things that evaluate like `true` would in certain positions \(e.g. `if` conditions and the boolean `&&` `||` operators\). The following things are truthy in JavaScript. An example is any number other than `0` e.g. 4 | 5 | ```typescript 6 | if (123) { // Will be treated like `true` 7 | console.log('Any number other than 0 is truthy'); 8 | } 9 | ``` 10 | 11 | Something that isn't truthy is called `falsy`. 12 | 13 | Here's a handy table for your reference. 14 | 15 | | Variable Type | When it is _falsy_ | When it is _truthy_ | 16 | | :--- | :--- | :--- | 17 | | `boolean` | `false` | `true` | 18 | | `string` | `''` \(empty string\) | any other string | 19 | | `number` | `0` `NaN` | any other number | 20 | | `null` | always | never | 21 | | `undefined` | always | never | 22 | | Any other Object including empty ones like `{}`,`[]` | never | always | 23 | 24 | ## Being explicit 25 | 26 | > The `!!` pattern 27 | 28 | Quite commonly it helps to be explicit that the intent is to treat the value as a `boolean` and convert it into a _true boolean_ \(one of `true`\|`false`\). You can easily convert values to a true boolean by prefixing it with `!!` e.g. `!!foo`. Its just `!` used _twice_. The first `!` converts the variable \(in this case `foo`\) to a boolean but inverts the logic \(_truthy_ -`!`> `false`, _falsy_ -`!`> `true`\). The second one toggles it again to match the nature of the original object \(e.g. _truthy_ -`!`> `false` -`!`> `true`\). 29 | 30 | It is common to use this pattern in lots of places e.g. 31 | 32 | ```javascript 33 | // Direct variables 34 | const hasName = !!name; 35 | 36 | // As members of objects 37 | const someObj = { 38 | hasName: !!name 39 | } 40 | 41 | // e.g. in ReactJS JSX 42 | {!!someName &&
{someName}
} 43 | ``` 44 | 45 | -------------------------------------------------------------------------------- /snippets/md-snippets.cson: -------------------------------------------------------------------------------- 1 | '.source.gfm': 2 | 'include': 3 | 'prefix': 'include' 4 | 'body': """ 5 | {% include "${1:./path}.md" %} 6 | """ -------------------------------------------------------------------------------- /tsx/README.md: -------------------------------------------------------------------------------- 1 | # JSX 2 | 3 | TypeScript supports JSX transpilation and code analysis. If you are unfamiliar with JSX here is an excerpt from the [official website](https://facebook.github.io/jsx/): 4 | 5 | > JSX is an XML-like syntax extension to ECMAScript without any defined semantics. It's NOT intended to be implemented by engines or browsers. It's NOT a proposal to incorporate JSX into the ECMAScript spec itself. It's intended to be used by various preprocessors \(transpilers\) to transform these tokens into standard ECMAScript. 6 | 7 | The motivation behind JSX is to allow users to write HTML like views _in JavaScript_ so that you can: 8 | 9 | * Have the view Type Checked by the same code that is going to check your JavaScript 10 | * Have the view be aware of the context it is going to operate under \(i.e. strengthen the _controller-view_ connection in traditional MVC\). 11 | * Reuse JavaScript patterns for HTML maintenance e.g. `Array.prototype.map`, `?:`, `switch` etc instead of creating new \(and probably poorly typed\) alternatives. 12 | 13 | This decreases the chances of errors and increases the maintainability of your user interfaces. The main consumer of JSX at this point is [ReactJS from facebook](http://facebook.github.io/react/). This is the usage of JSX that we will discuss here. 14 | 15 | -------------------------------------------------------------------------------- /tsx/others.md: -------------------------------------------------------------------------------- 1 | # Non React JSX 2 | 3 | TypeScript provides you with the ability to use something other than React with JSX in a type safe manner. The following lists the customizability points, but note that this is for advanced UI framework authors: 4 | 5 | * You can disable `react` style emit by using `"jsx" : "preserve"` option. This means that JSX is emitted _as is_ and then you can use your own custom transpiler to transpile the JSX portions. 6 | * Using the `JSX` global module: 7 | * You can control what HTML tags are available and how they are type checked by customizing the `JSX.IntrinsicElements` interface members. 8 | * When using components: 9 | * You can control which `class` must be inherited by components by customizing the default `interface ElementClass extends React.Component { }` declaration. 10 | * You can control which property is used to type check the attributes \(the default is `props`\) by customizing the `declare module JSX { interface ElementAttributesProperty { props: {}; } }` declaration. 11 | 12 | ## `jsxFactory` 13 | 14 | Passing `--jsxFactory ` along with `--jsx react` allows for using a different JSX factory from the default `React`. 15 | 16 | The new factory name will be used to call `createElement` functions. 17 | 18 | ### Example 19 | 20 | ```typescript 21 | import {jsxFactory} from "jsxFactory"; 22 | 23 | var div =
Hello JSX!
24 | ``` 25 | 26 | Compiled with: 27 | 28 | ```text 29 | tsc --jsx react --reactNamespace jsxFactory --m commonJS 30 | ``` 31 | 32 | Results in: 33 | 34 | ```javascript 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 | You can even specify a different `jsxFactory` per file using `jsxPragma` e.g. 43 | 44 | ```javascript 45 | /** @jsx jsxFactory */ 46 | import {jsxFactory} from "jsxFactory"; 47 | 48 | var div =
Hello JSX!
49 | ``` 50 | 51 | With `--jsx react` this file will emit to use the factory specfied in the jsx pragma: 52 | 53 | ```javascript 54 | "use strict"; 55 | var jsxFactory_1 = require("jsxFactory"); 56 | var div = jsxFactory_1.jsxFactory.createElement("div", null, "Hello JSX!"); 57 | ``` 58 | 59 | -------------------------------------------------------------------------------- /type-system/intro/README.md: -------------------------------------------------------------------------------- 1 | # Ambient Declarations 2 | 3 | As we mentioned in [why TypeScript](../../getting-started/why-typescript.md): 4 | 5 | > A major design goal of TypeScript was to make it possible for you to safely and easily use existing JavaScript libraries in TypeScript. TypeScript does this by means of _declaration_. 6 | 7 | Ambient declarations allow you to _safely use existing popular JavaScript libraries_ and _incrementally migrate your JavaScript/CoffeeScript/Other-Compile-To-Js-Language project to TypeScript_. 8 | 9 | Studying patterns in ambient declarations for _third party JavaScript code_ is good practice for annotating _your_ TypeScript code base as well. This is why we present it so early on. 10 | 11 | -------------------------------------------------------------------------------- /type-system/intro/d.ts.md: -------------------------------------------------------------------------------- 1 | # Declaration Files 2 | 3 | You can tell TypeScript that you are trying to describe code that exists elsewhere \(e.g. written in JavaScript/CoffeeScript/The runtime environment like the browser or Node.js\) using the `declare` keyword. As a quick example: 4 | 5 | ```typescript 6 | foo = 123; // Error: `foo` is not defined 7 | ``` 8 | 9 | vs. 10 | 11 | ```typescript 12 | declare var foo: any; 13 | foo = 123; // allowed 14 | ``` 15 | 16 | You have the option of putting these declarations in a `.ts` file or in a `.d.ts` file. We highly recommend that in your real world projects you use a separate `.d.ts` \(start with one called something like `globals.d.ts` or `vendor.d.ts`\). 17 | 18 | If a file has the extension `.d.ts` then each root level definition must have the `declare` keyword prefixed to it. This helps make it clear to the author that there will be _no code emitted by TypeScript_. The author needs to ensure that the declared item will exist at runtime. 19 | 20 | > * Ambient declarations is a promise that you are making with the compiler. If these do not exist at runtime and you try to use them, things will break without warning. 21 | > * Ambient declarations are like docs. If the source changes the docs need to be kept updated. So you might have new behaviours that work at runtime but no one's updated the ambient declaration and hence you get compiler errors. 22 | 23 | -------------------------------------------------------------------------------- /type-system/intro/variables.md: -------------------------------------------------------------------------------- 1 | # Variables 2 | 3 | For example to tell TypeScript about the [`process` variable](https://nodejs.org/api/process.html) you _can_ do: 4 | 5 | ```typescript 6 | declare var process: any; 7 | ``` 8 | 9 | > You don't _need_ to do this for `process` as there is already a [community maintained `node.d.ts`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/node/index.d.ts). 10 | 11 | This allows you to use the `process` variable without TypeScript complaining: 12 | 13 | ```typescript 14 | process.exit(); 15 | ``` 16 | 17 | We recommend using an interface wherever possible e.g.: 18 | 19 | ```typescript 20 | interface Process { 21 | exit(code?: number): void; 22 | } 23 | declare var process: Process; 24 | ``` 25 | 26 | This allows other people to _extend_ the nature of these global variables while still telling TypeScript about such modifications. E.g. consider the following case where we add an `exitWithLogging` function to process for our amusement: 27 | 28 | ```typescript 29 | interface Process { 30 | exitWithLogging(code?: number): void; 31 | } 32 | process.exitWithLogging = function() { 33 | console.log("exiting"); 34 | process.exit.apply(process, arguments); 35 | }; 36 | ``` 37 | 38 | Let's look at interfaces in a bit more detail next. 39 | 40 | -------------------------------------------------------------------------------- /type-system/types.md: -------------------------------------------------------------------------------- 1 | # @types 2 | 3 | [Definitivamente Typed](https://github.com/DefinitelyTyped/DefinitelyTyped) é um dos maiores pontos fortes do TypeScript. A comunidade foi adiante e **documentou** a natureza de quase 90% dos principais projetos de JavaScript existentes. 4 | 5 | Isso significa que você pode usar esses projetos de uma maneira muito interativa e exploratória, não é necessário ter os documentos abertos em uma janela separada e garantir que você não cometa erros de digitação. 6 | 7 | ## Usando `@types` 8 | 9 | A instalação é bastante simples, porque funciona apenas no topo do `npm`. Então, como um exemplo, você pode instalar definições de tipo para `jquery` simplesmente como: 10 | 11 | ```text 12 | npm install @types/jquery --save-dev 13 | ``` 14 | 15 | `@types` suporta as definições de tipo _global_ tanto como _module_. 16 | 17 | ### Global `@types` 18 | 19 | Por padrão, quaisquer definições que suportam o consumo global são incluídas automaticamente. Por exemplo. Para o jquery, você deve começar a usar `$` _globalmente_ em seu projeto. 20 | 21 | No entanto, para _bibliotecas_ \(como `jquery`\), geralmente recomendo usar _módulos_: 22 | 23 | ### Module `@types` 24 | 25 | Após a instalação, nenhuma configuração especial é realmente necessária. Você apenas importa-o como um módulo, ex.: 26 | 27 | ```typescript 28 | import * as $ from "jquery"; 29 | 30 | // Use $ à vontade neste módulo 😁 31 | ``` 32 | 33 | ## Controlando as variáveis globais 34 | 35 | Como pode ser visto, ter uma definição que permita o vazamento global automaticamente pode ser um problema para algumas equipes. Assim, você pode optar por trazer _explicitamente_ apenas os tipos que fazem sentido usando o `compilerOptions.types` `tsconfig.json`, por exemplo: 36 | 37 | ```javascript 38 | { 39 | "compilerOptions": { 40 | "types" : [ 41 | "jquery" 42 | ] 43 | } 44 | } 45 | ``` 46 | 47 | O exemplo acima mostra um exemplo onde somente o `jquery` poderá ser usado. Mesmo que a pessoa instale outra definição como o `npm install @types/node` seus globals \(por exemplo, [`process`](https://nodejs.org/api/process.html)\) não irão vazar para o seu código até que você os inclua na opção **types** no `tsconfig.json`. 48 | 49 | --------------------------------------------------------------------------------