├── .gitattributes ├── .github └── workflows │ ├── build.yml │ └── gpt-translate.yml ├── .gitignore ├── CONTRIBUTING.md ├── GLOSSARY.md ├── LICENSE.md ├── README.md ├── SUMMARY.md ├── book.json ├── code ├── async-await │ ├── es5 │ │ ├── asyncAwaitES5.js │ │ ├── asyncAwaitES5.ts │ │ └── tsconfig.json │ └── es6 │ │ ├── asyncAwaitES6.js │ │ ├── asyncAwaitES6.ts │ │ └── tsconfig.json ├── compiler │ ├── node_modules │ │ ├── .bin │ │ │ ├── ntsc │ │ │ ├── ntsc.cmd │ │ │ ├── ntse │ │ │ ├── ntse.cmd │ │ │ ├── ntsserver │ │ │ └── ntsserver.cmd │ │ └── ntypescript │ │ │ ├── .npmignore │ │ │ ├── .travis.yml │ │ │ ├── CONTRIBUTING.md │ │ │ ├── Gruntfile.js │ │ │ ├── LICENCE │ │ │ ├── README.md │ │ │ ├── appveyor.yml │ │ │ ├── bin │ │ │ ├── lib.core.d.ts │ │ │ ├── lib.core.es6.d.ts │ │ │ ├── lib.d.ts │ │ │ ├── lib.dom.d.ts │ │ │ ├── lib.es6.d.ts │ │ │ ├── lib.scriptHost.d.ts │ │ │ ├── lib.webworker.d.ts │ │ │ ├── ntypescript.d.ts │ │ │ ├── ntypescript.js │ │ │ ├── tsc │ │ │ ├── tsc.js │ │ │ ├── tse │ │ │ ├── tsserver │ │ │ ├── tsserver.js │ │ │ ├── typescript.d.ts │ │ │ ├── typescript.js │ │ │ ├── typescriptServices.d.ts │ │ │ └── typescriptServices.js │ │ │ ├── extensions │ │ │ ├── addExtensions.d.ts │ │ │ ├── addExtensions.js │ │ │ ├── addExtensions.ts │ │ │ ├── extensions.d.ts │ │ │ ├── extensions.js │ │ │ ├── extensions.ts │ │ │ └── tsconfig.json │ │ │ ├── kicktravis │ │ │ ├── package.json │ │ │ ├── prepare.sh │ │ │ ├── quick.sh │ │ │ ├── register.js │ │ │ ├── register.ts │ │ │ ├── release.sh │ │ │ ├── tasks │ │ │ ├── ntypescript.js │ │ │ └── ntypescript.ts │ │ │ ├── tsconfig.json │ │ │ ├── tsd.json │ │ │ ├── tse.js │ │ │ ├── tse.ts │ │ │ └── typings │ │ │ ├── gruntjs │ │ │ └── gruntjs.d.ts │ │ │ ├── node │ │ │ └── node.d.ts │ │ │ └── tsd.d.ts │ ├── package.json │ ├── parser │ │ ├── runParser.js │ │ └── runParser.ts │ ├── scanner │ │ ├── runScanner.js │ │ ├── runScanner.ts │ │ ├── runScannerWithPositions.js │ │ └── runScannerWithPositions.ts │ ├── tsconfig.json │ ├── tsd.json │ └── typings │ │ ├── node │ │ └── node.d.ts │ │ └── tsd.d.ts ├── declarationspaces │ ├── declarationspace.js │ └── declarationspace.ts ├── dynamic-import-expressions │ ├── dynamicImportExpression.js │ ├── dynamicImportExpression.ts │ ├── package.json │ └── tsconfig.json ├── errors │ ├── common-errors.ts │ ├── interpreting-errors.ts │ └── tsconfig.json ├── es6 │ ├── classes │ │ ├── abstract.js │ │ ├── abstract.ts │ │ ├── class.js │ │ ├── class.ts │ │ ├── super.js │ │ ├── super.ts │ │ └── tsconfig.json │ ├── const.js │ ├── const.ts │ ├── destructuring.js │ ├── destructuring.ts │ ├── enums.js │ ├── enums.ts │ ├── for..of.js │ ├── for..of.ts │ ├── forof.js │ ├── iterators.js │ ├── iterators.ts │ ├── let.js │ ├── let.ts │ ├── rest-parameters.js │ ├── rest-parameters.ts │ ├── spread-operator.js │ ├── spread-operator.ts │ ├── template-strings.js │ ├── template-strings.ts │ ├── test.js │ ├── test.ts │ └── tsconfig.json ├── javascript │ ├── closure.js │ ├── closure.ts │ └── tsconfig.json ├── tips │ ├── bindIsBad.js │ ├── bindIsBad.ts │ ├── currying.js │ ├── currying.ts │ ├── lazyObjectLiteralInitialization.js │ ├── lazyObjectLiteralInitialization.ts │ ├── mixins.js │ ├── mixins.ts │ ├── nominalTyping.js │ ├── nominalTyping.ts │ ├── statefulFunctions.js │ ├── statefulFunctions.ts │ ├── stringEnums.js │ ├── stringEnums.ts │ └── tsconfig.json └── types │ ├── assertion.js │ ├── assertion.ts │ ├── callable.ts │ ├── freshness │ ├── freshness.js │ ├── freshness.ts │ ├── index-signatures.js │ ├── index-signatures.ts │ └── tsconfig.json │ ├── functions.js │ ├── functions.ts │ ├── generics.js │ ├── generics.ts │ ├── interfaces.js │ ├── interfaces.ts │ ├── keyof.ts │ ├── lib │ ├── exclude │ │ ├── nolibd.js │ │ ├── nolibd.ts │ │ └── tsconfig.json │ └── usage │ │ ├── libd.js │ │ ├── libd.ts │ │ └── tsconfig.json │ ├── libd.js │ ├── literal-types.js │ ├── literal-types.ts │ ├── migrating │ ├── migrating.js │ ├── migrating.ts │ └── tsconfig.json │ ├── readonly.js │ ├── readonly.ts │ ├── stringLiteralType.js │ ├── tsconfig.json │ ├── type-compatibility.js │ ├── type-compatibility.ts │ ├── type-inference.js │ ├── type-inference.ts │ ├── typeGuard.js │ ├── typeGuard.ts │ ├── types.js │ └── types.ts ├── cover.jpg ├── docs ├── arrow-functions.md ├── async-await.md ├── classes-emit.md ├── classes.md ├── compiler-options.md ├── compiler │ ├── ast-tip-children.md │ ├── ast-tip-syntaxkind.md │ ├── ast-trivia.md │ ├── ast.md │ ├── binder-container.md │ ├── binder-declarations.md │ ├── binder-diagnostics.md │ ├── binder-functions.md │ ├── binder-symbolflags.md │ ├── binder-symboltable.md │ ├── binder.md │ ├── checker-diagnostics.md │ ├── checker-global.md │ ├── checker.md │ ├── contributing.md │ ├── emitter-functions.md │ ├── emitter-sourcemaps.md │ ├── emitter.md │ ├── make-global.md │ ├── overview.md │ ├── parser-functions.md │ ├── parser.md │ ├── program.md │ └── scanner.md ├── const.md ├── declaration.md ├── destructuring.md ├── enums.md ├── errors │ ├── common-errors.md │ ├── interpreting-errors.md │ └── main.md ├── for...of.md ├── future-javascript.md ├── generators.md ├── getting-started.md ├── iterators.md ├── javascript │ ├── closure.md │ ├── equality.md │ ├── null-undefined.md │ ├── number.md │ ├── recap.md │ ├── references.md │ ├── this.md │ └── truthy.md ├── jsx │ ├── others.md │ ├── react.md │ └── tsx.md ├── let.md ├── npm │ └── index.md ├── options │ ├── intro.md │ ├── noImplicitAny.md │ └── strictNullChecks.md ├── project │ ├── compilation-context.md │ ├── declarationspaces.md │ ├── dynamic-import-expressions.md │ ├── external-modules.md │ ├── files.md │ ├── globals.md │ ├── module-resolution.md │ ├── modules.md │ ├── namespaces.md │ ├── project.md │ └── tsconfig.md ├── promise.md ├── quick │ ├── browser.md │ ├── library.md │ └── nodejs.md ├── rest-parameters.md ├── spread-operator.md ├── staging │ ├── async-await.md │ └── generators.md ├── state │ └── mobx.md ├── styleguide │ ├── sample.js │ ├── sample.ts │ ├── styleguide.md │ └── tsconfig.json ├── template-strings.md ├── testing │ ├── cypress.md │ ├── intro.md │ └── jest.md ├── tips │ ├── barrel.md │ ├── build-toggles.md │ ├── classesAreUseful.md │ ├── create-arrays.md │ ├── currying.md │ ├── defaultIsBad.md │ ├── functionParameters.md │ ├── jquery.md │ ├── lazyObjectLiteralInitialization.md │ ├── main.md │ ├── nominalTyping.md │ ├── outFile.md │ ├── propertySetters.md │ ├── singleton.md │ ├── statefulFunctions.md │ ├── staticConstructor.md │ ├── stringEnums.md │ ├── typeInstantiation.md │ └── typed-event.md ├── tools │ ├── changelog.md │ ├── eslint.md │ ├── husky.md │ ├── intro.md │ └── prettier.md ├── types │ ├── @types.md │ ├── advanced.md │ ├── ambient │ │ ├── d.ts.md │ │ ├── intro.md │ │ └── variables.md │ ├── callable.md │ ├── discriminated-unions.md │ ├── exceptions.md │ ├── freshness.md │ ├── functions.md │ ├── generics.md │ ├── index-signatures.md │ ├── interfaces.md │ ├── lib.d.ts.md │ ├── literal-types.md │ ├── migrating.md │ ├── mixins.md │ ├── moving-types.md │ ├── never.md │ ├── readonly.md │ ├── type-assertion.md │ ├── type-compatibility.md │ ├── type-inference.md │ ├── type-system.md │ └── typeGuard.md └── why-typescript.md ├── footer.md ├── header.html ├── images ├── atomts.png ├── designtsx-banner-large.png ├── designtsx-banner.png ├── errors │ └── interpreting-errors │ │ └── ide.png ├── github.png ├── promise states and fates.png ├── promise states and fates.vsd ├── venn.png └── venn.vsd └── snippets └── md-snippets.cson /.gitattributes: -------------------------------------------------------------------------------- 1 | # core.autocrlf 2 | * text=auto 3 | 4 | *.js linguist-language=TypeScript 5 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build ebook 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | env: 15 | SHA: ${{ github.sha }} 16 | steps: 17 | - uses: actions/checkout@v3 18 | - uses: actions/setup-node@v3 19 | with: 20 | node-version: 16 21 | # required for calibre installation 22 | - run: | 23 | sudo add-apt-repository ppa:apt-fast/stable 24 | sudo apt-get update 25 | sudo apt-get install -y apt-fast 26 | sudo apt-fast update 27 | sudo apt-fast install -y python3 calibre 28 | # gitbook replaced by https://github.com/honkit/honkit 29 | - run: | 30 | npm install -g honkit 31 | npm install -g gitbook-plugin-edit-link 32 | npm install -g gitbook-plugin-github 33 | npm install -g gitbook-plugin-header 34 | # Compose books: https://honkit.netlify.app/ebook.html 35 | - run: | 36 | mkdir output 37 | npx honkit pdf ./ ./output/typescript-book-${SHA}.pdf 38 | npx honkit epub ./ ./output/typescript-book-${SHA}.epub 39 | npx honkit mobi ./ ./output/typescript-book-${SHA}.mobi 40 | - name: upload pdf artifact 41 | uses: actions/upload-artifact@v3 42 | with: 43 | name: typescript-book.pdf 44 | path: output/typescript-book-${{ env.SHA }}.pdf 45 | - name: upload epub artifact 46 | uses: actions/upload-artifact@v3 47 | with: 48 | name: typescript-book.epub 49 | path: output/typescript-book-${{ env.SHA }}.epub 50 | - name: upload mobi artifact 51 | uses: actions/upload-artifact@v3 52 | with: 53 | name: typescript-book.mobi 54 | path: output/typescript-book-${{ env.SHA }}.mobi 55 | -------------------------------------------------------------------------------- /.github/workflows/gpt-translate.yml: -------------------------------------------------------------------------------- 1 | # .github/workflows/gpt-translate.yml 2 | name: GPT Translate 3 | 4 | on: 5 | issue_comment: 6 | types: [ created ] 7 | 8 | jobs: 9 | gpt_translate: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v3 14 | 15 | - name: Run GPT Translate 16 | if: | 17 | contains(github.event.comment.body, '/gpt-translate') || 18 | contains(github.event.comment.body, '/gt') 19 | uses: 3ru/gpt-translate@v1.0 20 | with: 21 | apikey: ${{ secrets.OPENAI_API_KEY }} 22 | -------------------------------------------------------------------------------- /.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 | # Співпраця 2 | 3 | Ця книга розроблена з використанням [GitBook](https://github.com/GitbookIO/gitbook). Складається з Markdown файлів (Я використовую [atom](http://atom.io)). 4 | 5 | Як налаштувати оточення розробника (Dev Environment): 6 | 7 | ``` 8 | npm install gitbook-cli -g 9 | gitbook install 10 | gitbook serve . 11 | ``` 12 | > Зверніть увагу: serve використовує порт `35729` (для онлайн перезавантаженя) та `4000` для роботи http://localhost:4000. 13 | 14 | Також можна просто редагувати `.md` файли в [`/docs`](https://github.com/basarat/typescript-book/docs) використовуючи github і створити Pull Request (PR). 15 | 16 | # Код 17 | Увесь код для книги знаходиться в папці `/code`. Проткстовано за допомогою `atom-typescript`. 18 | 19 | ### Додаткові рекомендації з Gitbook 20 | * Послилання краще пряцюють, якщо вони відносні (наприклад, `./foo.md`) для *поточного* файлу. 21 | * Для посилань всередині певного файлу (посилання у стилі `#foo-bar`) краще кліенути на заголовку у github, щоб зрозуміти, що очікує gitbook. 22 | 23 | ### Документація компілятора TypeScript 24 | Дякую команді TypeScript за надання документації https://github.com/Microsoft/TypeScript/wiki/Architectural-Overview, що використовується для написання compiler story. -------------------------------------------------------------------------------- /GLOSSARY.md: -------------------------------------------------------------------------------- 1 | # Качина типізація 2 | Якщо воно виглядає як качка, плаває як качка і кахкає як качка, то це напевно і є качка. Для TypeScript якщо щось має всі елементи структурно, тоді це підходить і для інших речей (незважаючи на імʼя), які приймають цю структуру. 3 | 4 | # ОО 5 | Операційне оточення. Я би хотів використовувати термін Опепаційна Система, але це не обов'язково те, що я маю на увазі. Xbnfq Browser,Node.js,WScriptHost і т.ін. 6 | 7 | # Інкерементальний парсинг 8 | Перезапуск парсингу під час редагування коду користувачем. -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Creative Commons 2 | 3 | https://creativecommons.org/licenses/by/4.0/ 4 | -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | { 2 | "language": "ua", 3 | "author": "Basarat Ali Syed, Oleksandr Kucherenko (transalation)", 4 | "title": "TypeScript Повне Занурення", 5 | "plugins": ["edit-link", "github", "header"], 6 | "pluginsConfig": { 7 | "layout": { 8 | "headerPath": "header.html" 9 | }, 10 | "lunr": { 11 | "ignoreSpecialCharacters": true 12 | }, 13 | "edit-link": { 14 | "base": "https://github.com/ArtfulBits/typescript-book/tree/master", 15 | "label": "Edit This Page" 16 | }, 17 | "github": { 18 | "url": "https://github.com/ArtfulBits/typescript-book" 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /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 const 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/ArtfulBits/typescript-book/b140230f7a46921e011db81728019ea00900183f/code/es6/test.js -------------------------------------------------------------------------------- /code/es6/test.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtfulBits/typescript-book/b140230f7a46921e011db81728019ea00900183f/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 | module first { 4 | function logName(something: { name: string }) { 5 | console.log(something.name); 6 | } 7 | 8 | var person = { name: 'matt', job: 'being awesome' }; 9 | var animal = { name: 'cow', diet: 'vegan, but has milk of own species' }; 10 | var random = { note: `I don't have a name property` }; 11 | 12 | logName(person); // okay 13 | logName(animal); // okay 14 | logName(random); // Error : property `name` is missing 15 | } 16 | 17 | module second { 18 | function logName(something: { name: string }) { 19 | console.log(something.name); 20 | } 21 | 22 | logName({ name: 'matt' }); // okay 23 | logName({ name: 'matt', job: 'being awesome' }); // Error: object literals must only specify known properties. `job` is excessive here. 24 | } 25 | 26 | module third { 27 | function logIfHasName(something: { name?: string }) { 28 | if (something.name) { 29 | console.log(something.name); 30 | } 31 | } 32 | var person = { name: 'matt', job: 'being awesome' }; 33 | var animal = { name: 'cow', diet: 'vegan, but has milk of own species' }; 34 | 35 | logIfHasName(person); // okay 36 | logIfHasName(animal); // okay 37 | logIfHasName({ neme: 'I just misspelled name to neme' }); // Error: object literals must only specify known properties. `neme` is excessive here. 38 | } 39 | 40 | module fourth { 41 | var x: { foo: number; [x: string]: any }; 42 | x = { foo: 1, baz: 2 }; // Ok, `baz` matched by index signature 43 | } 44 | 45 | module fifth { 46 | // Assuming 47 | interface State { 48 | foo: string; 49 | bar: string; 50 | } 51 | 52 | class MyComponent { 53 | state: any; 54 | 55 | setState(state: State) { 56 | /* ... */ 57 | } 58 | 59 | doSomething() { 60 | // You want to do: 61 | this.setState({ foo: 'Hello' }); // Error: missing property bar 62 | 63 | // But because state contains both `foo` and `bar` TypeScript would force you to do: 64 | this.setState({ foo: 'Hello', bar: this.state.bar }); 65 | } 66 | } 67 | } 68 | 69 | module sixth { 70 | // Assuming 71 | interface State { 72 | foo?: string; 73 | bar?: string; 74 | } 75 | 76 | class MyComponent { 77 | state: any; 78 | 79 | setState(state: State) { 80 | /* ... */ 81 | } 82 | 83 | doSomething() { 84 | // You want to do: 85 | this.setState({ foo: 'Hello' }); // Yay works fine! 86 | 87 | // Because of freshness it's protected against typos as well! 88 | this.setState({ foos: 'Hello' }); // Error: Objects may only specify known properties 89 | 90 | // And still type checked 91 | this.setState({ foo: 123 }); // Error: Cannot assign number to a string 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /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/ArtfulBits/typescript-book/b140230f7a46921e011db81728019ea00900183f/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/ArtfulBits/typescript-book/b140230f7a46921e011db81728019ea00900183f/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/ArtfulBits/typescript-book/b140230f7a46921e011db81728019ea00900183f/cover.jpg -------------------------------------------------------------------------------- /docs/compiler-options.md: -------------------------------------------------------------------------------- 1 | // mention Pinned comments 2 | 3 | ```ts 4 | /*! 5 | * License 6 | */ 7 | ``` 8 | -------------------------------------------------------------------------------- /docs/compiler/ast-tip-children.md: -------------------------------------------------------------------------------- 1 | ### AST Порада: Visit Children 2 | 3 | Існує допоміжна функція `ts.forEachChild` яка дозволяє відвідувати всі дочірні вузли будь-якого Node в AST. 4 | 5 | Нижче наведений спрощений фрагмент вихідного (програмного) коду, щоб продемонструвати, як він працює: 6 | 7 | ```ts 8 | 9 | export function forEachChild(node: Node, cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T { 10 | if (!node) { 11 | return; 12 | } 13 | switch (node.kind) { 14 | case SyntaxKind.BinaryExpression: 15 | return visitNode(cbNode, (node).left) || 16 | visitNode(cbNode, (node).operatorToken) || 17 | visitNode(cbNode, (node).right); 18 | case SyntaxKind.IfStatement: 19 | return visitNode(cbNode, (node).expression) || 20 | visitNode(cbNode, (node).thenStatement) || 21 | visitNode(cbNode, (node).elseStatement); 22 | 23 | // .... lots more 24 | ``` 25 | 26 | На практиці ця функція перевіряє значення `node.kind` та, виходячи з цього, вважає, який інтерфейс пропонується `node` і викликає `cbNode` для дочірніх елементів вузла. Зверніть увагу, що ця функція не викликає `visitNode` для *всіх* дочірніх елементів (наприклад, SyntaxKind.SemicolonToken). Якщо вам потрібно отримати *всі* дочірні елементи вузла у AST, просто викличте метод `.getChildren` об'єкта Node. 27 | 28 | Наприклад, ось функція, яка виводить докладний AST вузла: 29 | 30 | ```ts 31 | function printAllChildren(node: ts.Node, depth = 0) { 32 | console.log(new Array(depth+1).join('----'), ts.syntaxKindToName(node.kind), node.pos, node.end); 33 | depth++; 34 | node.getChildren().forEach(c=> printAllChildren(c, depth)); 35 | } 36 | ``` 37 | 38 | Ми побачимо приклад використання цієї функції, коли будемо детальніше обговорювати парсер. 39 | -------------------------------------------------------------------------------- /docs/compiler/ast-tip-syntaxkind.md: -------------------------------------------------------------------------------- 1 | ### AST Порада: SyntaxKind 2 | 3 | `SyntaxKind` визначений як `const enum`, ось приклад : 4 | 5 | ```ts 6 | export const enum SyntaxKind { 7 | Unknown, 8 | EndOfFileToken, 9 | SingleLineCommentTrivia, 10 | // ... LOTS more 11 | ``` 12 | 13 | Це `const enum` (концепція [яку ми розглянули раніше](../enums.md)). Вона використовується для того, щоб перелік *вбудовувався* безпосередньо у код, замість створення об'єкта переліку. 14 | Коли ми використовуємо const enum, значення переліку замінюється прямо в місці використання (наприклад, `ts.SyntaxKind.EndOfFileToken` буде замінено на фактичне значення `1` в усіх місцях, де використовується цей перелік). 15 | 16 | Один з основних переваг використання const enum полягає в тому, що ми уникаємо витрат на дереференцію (dereferencing cost), тобто на доступ до об'єкта переліку під час роботи з AST. Оскільки значення вбудовуються безпосередньо в код, нам не потрібно звертатися до об'єкта переліку, що полегшує та прискорює роботу з AST. 17 | 18 | Однак, компілятор компілюється з прапорцем `--preserveConstEnums` тому перелік *все ще доступний під час виконання*. Одже, в JavaScript ви можете використовувати `ts.SyntaxKind.EndOfFileToken`, якщо бажаєте. Крім того, ви можете перетворити ці елементи переліку у рядки для відображення за допомогою наступної функції: 19 | 20 | ```ts 21 | export function syntaxKindToName(kind: ts.SyntaxKind) { 22 | return (ts).SyntaxKind[kind]; 23 | } 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/compiler/ast.md: -------------------------------------------------------------------------------- 1 | ## Вузол (Node) 2 | Основним будівельним блоком Абстрактного Синтаксичного Дерева (AST) є Node. В загальному випадку, Node представляє нелематичні (non-terminals) символи в граматиці мови, проте деякі лематичні символи, такі як ідентифікатори і літерали, також зберігаються у дереві. 3 | 4 | Документація вузла AST складається з двох основних елементів: `SyntaxKind`, який ідентифікує тип вузла в межах AST, і `interface`, API, яке вузол надає під час інстанціювання в AST. 5 | 6 | Нижче наведені ключові елементи `interface Node`: 7 | * `TextRange` визначають `початок` та `кінець` вузла в вихідному файлі. 8 | * `parent?: Node` батьківський вузол в AST. 9 | 10 | У інтерфейсі Node є й інші додаткові елементи, такі як прапорці (flags) та модифікатори (modifiers), які визначають додаткові властивості та характеристики вузлів абстрактного синтаксичного дерева (AST). Ці додаткові елементи надають більше інформації про вузли та їхні властивості, і можуть бути корисними для певних операцій і обробки AST. Докладнішу інформацію можна знайти за допомогою ключового слова `interface Node` в у вихідному коді. Однак, для навігації та обходу AST, основними та важливими членами Node є ті, які були згадані в початковому поясненні. 11 | 12 | ## Вихідний файл (SourceFile) 13 | 14 | * `SyntaxKind.SourceFile` 15 | * `interface SourceFile`. 16 | 17 | Кожен `SourceFile` є верхнім вузлом абстрактного синтаксичного дерева (AST), який міститься в `Program`. 18 | -------------------------------------------------------------------------------- /docs/compiler/binder-declarations.md: -------------------------------------------------------------------------------- 1 | ### Символи та декларації 2 | Посилання між `node` та `symbol` встановлюється за допомогою кількох функцій. Одна з таких функцій, яка використовується для зв'язку між вузлом `SourceFile` та символом вихідного файлу (у випадку зовнішнього модуля), - це функція `addDeclarationToSymbol`. 3 | 4 | Примітка: `Symbol` для вихідного файлу зовнішнього модуля встановлюється як `flags : SymbolFlags.ValueModule` та `name: '"' + removeFileExtension(file.fileName) + '"'`). 5 | 6 | ```ts 7 | function addDeclarationToSymbol(symbol: Symbol, node: Declaration, symbolFlags: SymbolFlags) { 8 | symbol.flags |= symbolFlags; 9 | 10 | node.symbol = symbol; 11 | 12 | if (!symbol.declarations) { 13 | symbol.declarations = []; 14 | } 15 | symbol.declarations.push(node); 16 | 17 | if (symbolFlags & SymbolFlags.HasExports && !symbol.exports) { 18 | symbol.exports = {}; 19 | } 20 | 21 | if (symbolFlags & SymbolFlags.HasMembers && !symbol.members) { 22 | symbol.members = {}; 23 | } 24 | 25 | if (symbolFlags & SymbolFlags.Value && !symbol.valueDeclaration) { 26 | symbol.valueDeclaration = node; 27 | } 28 | } 29 | ``` 30 | 31 | Важливі сполучні частини: 32 | * Створює посилання на символ з вузла AST (`node.symbol`). 33 | * Додає вузол як *одну з* декларацій символу (`symbol.declarations`). 34 | 35 | #### Декларація 36 | Декларація у `types.ts` це лише `node` із необов’язковим ім’ям. 37 | 38 | ```ts 39 | interface Declaration extends Node { 40 | _declarationBrand: any; 41 | name?: DeclarationName; 42 | } 43 | ``` 44 | -------------------------------------------------------------------------------- /docs/compiler/binder-diagnostics.md: -------------------------------------------------------------------------------- 1 | ### Повідомлення про помилки зв'язування (Binder Error Reporting) 2 | 3 | Помилки зв'язування додаються до списку `bindDiagnostics` вихідного файлу. 4 | 5 | Прикладом помилки, виявленої під час зв'язування, є використання `eval` або `arguments` як назви змінної в сценарії з включеним режимом `use strict`. Відповідний код наведено повністю нижче (`checkStrictModeEvalOrArguments` викликається з різних місць, стеки викликів походять з `bindWorker` який викликає різні функції для різних `SyntaxKind` вузлів): 6 | 7 | ```ts 8 | function checkStrictModeEvalOrArguments(contextNode: Node, name: Node) { 9 | if (name && name.kind === SyntaxKind.Identifier) { 10 | let identifier = name; 11 | if (isEvalOrArgumentsIdentifier(identifier)) { 12 | // We check first if the name is inside class declaration or class expression; if so give explicit message 13 | // otherwise report generic error message. 14 | let span = getErrorSpanForNode(file, name); 15 | file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, 16 | getStrictModeEvalOrArgumentsMessage(contextNode), identifier.text)); 17 | } 18 | } 19 | } 20 | 21 | function isEvalOrArgumentsIdentifier(node: Node): boolean { 22 | return node.kind === SyntaxKind.Identifier && 23 | ((node).text === "eval" || (node).text === "arguments"); 24 | } 25 | 26 | function getStrictModeEvalOrArgumentsMessage(node: Node) { 27 | // Provide specialized messages to help the user understand why we think they're in 28 | // strict mode. 29 | if (getContainingClass(node)) { 30 | return Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode; 31 | } 32 | 33 | if (file.externalModuleIndicator) { 34 | return Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode; 35 | } 36 | 37 | return Diagnostics.Invalid_use_of_0_in_strict_mode; 38 | } 39 | ``` 40 | -------------------------------------------------------------------------------- /docs/compiler/binder-functions.md: -------------------------------------------------------------------------------- 1 | ### Функції зв'язування (Binder) 2 | Дві ключові функції зв'язування - це `bindSourceFile` та `mergeSymbolTable`. Давайте розглянемо їх детальніше. 3 | 4 | #### `bindSourceFile` 5 | В основному перевіряє, чи визначений `file.locals`. Якщо ні, він передає управління функції `bind` (локальній функції). 6 | 7 | Примітка: `locals` визначено у `Node` і має тип `SymbolTable`. Зверніть увагу, що `SourceFile` також є `Node` (фактично кореневим вузлом в AST). 8 | 9 | ПОРАДА: локальні функції широко використовуються в компіляторі TypeScript. Локальна функція, скоріш за все, використовує змінні з батьківської функції (захоплені за допомогою замикання). У випадку `bind` (локальна функція в межах `bindSourceFile`) вона (або функція, яку вона викликає) налаштовує `symbolCount`, `classifiableNames` та інші значення, які потім зберігаються у поверненому `SourceFile`. 10 | 11 | #### `bind` 12 | Функція `bind` працює з будь-яким об'єктом типу `Node` (не тільки з `SourceFile`). По-перше, вона призначає значення для `node.parent` (якщо змінна `parent` була налаштована... це також те, що `binder` робить під час обробки в межах функції `bindChildren`), далі передає управління до функції `bindWorker`, яка виконує *основну* роботу. Нарешті, вона викликає функцію `bindChildren` (функція, яка просто зберігає стан `binder`, наприклад, поточний `parent`, у своїх локальних змінних, далі викликає `bind` для кожного дочірнього вузла і наостанок, відновлює стан байндера). Тепер давайте розглянемо найцікавішу функцію `bindWorker`. 13 | 14 | #### `bindWorker` 15 | Ця функція вмикає `node.kind` (типу `SyntaxKind`) і делегує роботу відповідній функції `bindFoo` (також визначеної у `binder.ts`). Наприклад, якщо `node` є `SourceFile` він викликає (у випадку зовнішнього модуля файлу) `bindAnonymousDeclaration` 16 | 17 | #### `bindFoo` 18 | Існують кілька типових шаблонів для функцій `bindFoo`, а також кілька вспоміжних функцій, якими вони користуються. Одна функція, яка майже завжди використовується, - це функція `createSymbol`. Нижче наведено її повний варіант: 19 | 20 | ```ts 21 | function createSymbol(flags: SymbolFlags, name: string): Symbol { 22 | symbolCount++; 23 | return new Symbol(flags, name); 24 | } 25 | ``` 26 | Як можна побачити, `bindFoo` просто оновлює значення `symbolCount` (локальної змінної в функції `bindSourceFile`) та створює символ із вказаними параметрами. 27 | -------------------------------------------------------------------------------- /docs/compiler/binder.md: -------------------------------------------------------------------------------- 1 | ## Байндер (Binder) 2 | Більшість існуючих JavaScript транспіляторів (інструменти, які перетворюють код, написаний на одній версії JS, в код, сумісний з іншою або попередньою версією) простіші за TypeScript, оскільки вони надають обмежені можливості аналізу коду. Типові транспілятори JavaScript мають лише такий потік роботи: 3 | 4 | ```ts 5 | SourceCode ~~Scanner~~> Tokens ~~Parser~~> AST ~~Emitter~~> JavaScript 6 | ``` 7 | Хоча наведена вище архітектура вірна як спрощене розуміння генерації TypeScript, ключовою особливістю є його *семантична* система. `binder` (у `binder.ts`) використовується для з’єднання різних частин вихідного коду в узгоджену систему типів, яку згодом використовує `checker`(який ці типи і перевіряє). Основна відповідальність байндера полягає у створенні _Symbols_. 8 | 9 | 10 | ### Символи (Symbol) 11 | Символи з'єднують вузли декларацій в AST з іншими деклараціями, що вносять внесок у саму сутність. Символи є основними будівельними блоками семантичної системи. Конструктор символа визначений у файлі `core.ts`. В свою чергу `binder` використовує `objectAllocator.getSymbolConstructor`, щоб отримати доступ до конструктора. Нижче наведений Symbol конструктор: 12 | 13 | ```ts 14 | function Symbol(flags: SymbolFlags, name: string) { 15 | this.flags = flags; 16 | this.name = name; 17 | this.declarations = undefined; 18 | } 19 | ``` 20 | 21 | `SymbolFlags` є перерахуванням (enum) прапорців і фактично використовується для ідентифікацій додаткових класифікацій символів (наприклад, прапорців області видимості змінної, таких як `FunctionScopedVariable` або `BlockScopedVariable`). 22 | 23 | ### Usage by Checker 24 | Внутрішньо `binder` використовується типом `checker`, який в свою чергу використовується `program`. Спрощений стек викликів виглядає так: 25 | 26 | ``` 27 | program.getTypeChecker -> 28 | ts.createTypeChecker (in checker)-> 29 | initializeTypeChecker (in checker) -> 30 | for each SourceFile `ts.bindSourceFile` (in binder) 31 | // followed by 32 | for each SourceFile `ts.mergeSymbolTable` (in checker) 33 | ``` 34 | 35 | Одиницею роботи для `binder` є `SourceFile`. `binder.ts` керується `checker.ts`. 36 | -------------------------------------------------------------------------------- /docs/compiler/checker-diagnostics.md: -------------------------------------------------------------------------------- 1 | ### Перевірка звітів про помилки 2 | Засіб перевірки використовує локальну функцію `error` для повідомлення про помилки. Нижче приведений код функції: 3 | 4 | ```ts 5 | function error(location: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): void { 6 | let diagnostic = location 7 | ? createDiagnosticForNode(location, message, arg0, arg1, arg2) 8 | : createCompilerDiagnostic(message, arg0, arg1, arg2); 9 | diagnostics.add(diagnostic); 10 | } 11 | ``` 12 | -------------------------------------------------------------------------------- /docs/compiler/checker-global.md: -------------------------------------------------------------------------------- 1 | ### Об'єднання глобального простору імен 2 | У межах функції `initializeTypeChecker` існує наступний код: 3 | 4 | ```ts 5 | // Initialize global symbol table 6 | forEach(host.getSourceFiles(), file => { 7 | if (!isExternalModule(file)) { 8 | mergeSymbolTable(globals, file.locals); 9 | } 10 | }); 11 | ``` 12 | 13 | Це в основному об'єднує всі символи `global` в `let globals: SymbolTable = {};` (всередині функції `createTypeChecker`) таблиці символів SymbolTable. Функція `mergeSymbolTable` переважно викликає іншу функцію `mergeSymbol`. 14 | -------------------------------------------------------------------------------- /docs/compiler/checker.md: -------------------------------------------------------------------------------- 1 | ## Checker 2 | Як ми вже згадували раніше *checker* - це те, що робить TypeScript унікально потужним у порівнянні з *просто ще одним транспілером JavaScript*. `Checker` розташований у файлі `checker.ts` і на даний момент складається з понад 23 тис. рядків коду на TypeScript (найбільша частина компілятора). 3 | 4 | ### Використання програмою 5 | `Checker` ініціалізується об'єктом `program`. Нижче наведений невеликий приклад стеку викликів (ми використовували той самий приклад при дослідженні `binder`): 6 | 7 | ``` 8 | program.getTypeChecker -> 9 | ts.createTypeChecker (in checker)-> 10 | initializeTypeChecker (in checker) -> 11 | for each SourceFile `ts.bindSourceFile` (in binder) 12 | // followed by 13 | for each SourceFile `ts.mergeSymbolTable` (in checker) 14 | ``` 15 | 16 | ### Пов'язаність з генератором коду 17 | Справжня перевірка типу відбувається після виклику `getDiagnostics`. Ця функція викликається наприклад, коли запит зроблений до `Program.emit`, в такому випадку `checker` повертає `EmitResolver` (програма викликає функцію `getEmitResolver` чекера) який представляє собою набір функцій, локальних для `createTypeChecker`. Ми ще повернемося до цього, коли будемо розглядати `emitter`. 18 | 19 | Нижче наведений стек викликів, що веде до `checkSourceFile` (функції, що локально присутня у `createTypeChecker`). 20 | 21 | ``` 22 | program.emit -> 23 | emitWorker (program local) -> 24 | createTypeChecker.getEmitResolver -> 25 | // First call the following functions local to createTypeChecker 26 | call getDiagnostics -> 27 | getDiagnosticsWorker -> 28 | checkSourceFile 29 | 30 | // then 31 | return resolver 32 | (already initialized in createTypeChecker using a call to local createResolver()) 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/compiler/emitter.md: -------------------------------------------------------------------------------- 1 | ## Еміттер 2 | Існує два `еміттера` в компіляторі TypeScript: 3 | 4 | * `emitter.ts`: це еміттер, який ймовірно вас цікавить найбільше. Він виконує перетворення з TS у JavaScript. 5 | * `declarationEmitter.ts`: це еміттер, який використовується для створення *файлу оголошення* (`.d.ts`) для *файлу з вихідним кодом TypeScript* (`.ts`). 6 | 7 | У цьому розділі ми розглянемо `emitter.ts`. 8 | 9 | ### Використання класом `Program` 10 | Клас `Program` надає функцію `emit`. Ця функція переважно делегує виклик до функції `emitFiles` у файлі `emitter.ts`. Нижче наведено стек викликів: 11 | 12 | ``` 13 | Program.emit -> 14 | `emitWorker` (local in program.ts createProgram) -> 15 | `emitFiles` (function in emitter.ts) 16 | ``` 17 | 18 | Одним з аргументів, який `emitWorker` передає еміттеру (через `emitFiles`), є `EmitResolver`. `EmitResolver` надається від програми TypeChecker і, по суті, він є підмножиною *локальних* функцій з `createChecker`. 19 | -------------------------------------------------------------------------------- /docs/compiler/make-global.md: -------------------------------------------------------------------------------- 1 | ## Зробити TypeScript глобальним. 2 | 3 | TypeScript ітмплеменований за допомогою `namespace ts`. Весь код компілюється в один файл `typescript.js`. 4 | Якщо вам потрібно скопіювати частини вихідного коду для дослідження, кращим способом зробити це призначити їх в глобальну змінну `ts`. 5 | 6 | Щоб зрозуміти як працює TypeScript комілятор, можна додати його вихідний код у папку, а потім посилатися на нього як на `глобальну` змінну. 7 | 8 | -------------------------------------------------------------------------------- /docs/compiler/program.md: -------------------------------------------------------------------------------- 1 | ## Program 2 | 3 | Визначається у файлі `program.ts`. Контекст компіляції ([поняття, яке ми розглядали раніше](../project/compilation-context.md)) представлено у компіляторі TypeScript як `Program`. Він складається з `SourceFile` та опцій компілятора. 4 | 5 | 6 | ### Використання `CompilerHost` 7 | Механізм його взаємодії з операційним оточенням: 8 | 9 | `Program` *-uses->* `CompilerHost` *-uses->* `System` 10 | 11 | Причиною використання `CompilerHost` як точки опосередкування є те, що це дозволяє тонше налаштувати інтерфейс для потреб `Program` і не турбуватися про потреби операційного оточення (наприклад, `Program` не турбується про функцію `fileExists`, надану `System`). 12 | 13 | Такод є й інші користувачі `System` (наприклад, тести). 14 | 15 | ### SourceFile 16 | 17 | Програма надає API для отримання вихідних файлів `getSourceFiles(): SourceFile[];`. Кожен з них представлено у вигляді вузла кореневого рівня для AST (який називається `SourceFile`). 18 | -------------------------------------------------------------------------------- /docs/const.md: -------------------------------------------------------------------------------- 1 | ### const 2 | Константи. 3 | 4 | `const` є дуже бажаним доповненням, запропонованим ES6/TypeScript. Це дозволяє вам створювати змінні, значення которих не можно змінити. Це добре як з точки зору документації, так і з точки зору часу виконання. Щоб використовувати const, просто замініть `var` або `let` на `const`: 5 | 6 | ```ts 7 | const foo = 123; 8 | ``` 9 | 10 | > Синтаксис TS набагато кращий (IMHO), ніж у інших мовах, які змушують користувача вводити щось на зразок `let constant foo` , тобто змінна + специфікатор поведінки. 11 | 12 | `const` є хорошою практикою як для зручності читання, так і для підтримки та уникає використання *magic literals* ("магічних" значень), наприклад 13 | 14 | ```ts 15 | // Низька читабельність та не зрозуміло, чому саме 10? 16 | if (x > 10) { 17 | } 18 | 19 | // Краще! 20 | const maxRows = 10; 21 | if (x > maxRows) { 22 | } 23 | ``` 24 | 25 | #### const declarations must be initialized 26 | 27 | ВАЖЛИВО! Константа повинна отримати значення при створені. 28 | 29 | Нижче наведено помилку компілятора: 30 | 31 | ```ts 32 | const foo; // ПОМИЛКА: необхідно ініціалізувати оголошення const 33 | ``` 34 | 35 | #### Left hand side of assignment cannot be a constant 36 | 37 | Константи є незмінними після створення, тому якщо ви спробуєте призначити їм нове значення, це буде помилкою компілятора: 38 | 39 | ```ts 40 | const foo = 123; 41 | foo = 456; // ПОМИЛКА 42 | ``` 43 | 44 | #### Block Scoped 45 | 46 | `Const` має блочну область видимості , як ми бачили з [`let`](./let.md): 47 | 48 | ```ts 49 | const foo = 123; 50 | if (true) { 51 | const foo = 456; // Можливо, тому що це інша знінна foo 52 | } 53 | ``` 54 | 55 | #### Deep immutability 56 | 57 | `const` також працює з об’єктними літералами, в цьому припаді незмінною є *reference* (посилання) на змінну: 58 | 59 | ```ts 60 | const foo = { bar: 123 }; 61 | foo = { bar: 456 }; // // ПОМИЛКА: не можна присвоїти змінній інший обʼєкт 62 | ``` 63 | 64 | Однак він все ще дозволяє змінювати властивості об’єктів, як показано нижче: 65 | 66 | ```ts 67 | const foo = { bar: 123 }; 68 | foo.bar = 456; // Allowed! 69 | console.log(foo); // { bar: 456 } 70 | ``` 71 | 72 | #### Prefer const 73 | 74 | Завжди використовуйте const , якщо ви не плануєте пізніше ініціалізувати змінну, або виконати перепризначення (використовуйте let для таких випадків). 75 | -------------------------------------------------------------------------------- /docs/declaration.md: -------------------------------------------------------------------------------- 1 | analogy with c headers 2 | -------------------------------------------------------------------------------- /docs/errors/common-errors.md: -------------------------------------------------------------------------------- 1 | # Поширені помилки 2 | У цьому розділі ми пояснюємо деякі поширені коди помилок, з якими користувачі стикаються в реальному кодуванні. 3 | 4 | ## TS2304 5 | Приклади: 6 | > `Cannot find name ga` 7 | > `Cannot find name $` 8 | > `Cannot find module jquery` 9 | 10 | Можливо, ви використовуєте сторонню бібліотеку (наприклад, google analytics) і не задекларували її. TypeScript намагається вберегти вас від *орфографічних помилок* та *використання змінних без їх оголошення*, тому вам потрібно явно вказати все, що є *доступним під час виконання*, включаючи зовнішні бібліотеки ([детальніше про способи виправлення][ambient]). 11 | 12 | ## TS2307 13 | Приклад: 14 | > `Cannot find module 'underscore'` 15 | 16 | Ви, ймовірно, використовуєте сторонню бібліотеку (наприклад, underscore) як *модуль* ([докладніше про модулі][modules]) але не маєте файлу оголошення для нього ([детальніше про оголошення на ambient][ambient]). 17 | 18 | ## TS1148 19 | Приклад: 20 | > Cannot compile modules unless the '--module' flag is provided 21 | 22 | Перевірте [розділ про модулі][modules]. 23 | 24 | ## Catch clause variable cannot have a type annotation 25 | Змінна в операторі catch не може мати анотацію типу 26 |
27 | Приклад: 28 | ```js 29 | try { something(); } 30 | catch (e: Error) { // Catch clause variable cannot have a type annotation 31 | } 32 | ``` 33 | TypeScript захищає вас від некоректного JavaScript-коду зі сторони. Використайте замість цього захист типів (type guard): 34 | ```js 35 | try { something(); } 36 | catch (e) { 37 | if (e instanceof Error){ 38 | // Here you go. 39 | } 40 | } 41 | ``` 42 | 43 | ## Interface `ElementClass` cannot simultaneously extend types `Component` and `Component` 44 | Інтерфейс ElementClass не може одночасно розширювати типи Component та Component. 45 |
46 | Це відбувається, коли у контексті компіляції є два файлу `react.d.ts` (`@types/react/index.d.ts`). 47 | 48 | **Виправити**: 49 | * Видаліть `node_modules` і будь-який `package-lock` (або yarn lock) і знову виконайте `npm install`. 50 | * Якщо це не працює, знайдіть невірний модуль (всі модулі, що використовуються вашим проектом, повинні мати `react.d.ts` як `peerDependency`, а не як жорстку `dependency`) і зазначте це у своєму проекті. 51 | 52 | 53 | [ambient]: ../types/ambient/d.ts.md 54 | [modules]: ../project/modules.md 55 | -------------------------------------------------------------------------------- /docs/errors/main.md: -------------------------------------------------------------------------------- 1 | # Помилки 2 | У цьому розділі ми обговоримо, як читати і розуміти помилки TypeScript. Після цього ми розглянемо типові помилки та способи їх усунення. -------------------------------------------------------------------------------- /docs/future-javascript.md: -------------------------------------------------------------------------------- 1 | # Future JavaScript: Now 2 | 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. 3 | 4 | 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 ;) 5 | -------------------------------------------------------------------------------- /docs/javascript/closure.md: -------------------------------------------------------------------------------- 1 | ## Замикання 2 | 3 | Найкращою рисою, яку отримав JavaScript, є замикання. Функція в JavaScript має доступ до будь-яких змінних, що визначені у зовнішньому області видимості. Замикання найкраще пояснити на прикладах: 4 | 5 | ```ts 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 | Ви можете помітити, що внутрішня функція має доступ до змінної (variableInOuterFunction) зовнішнього контексту. Змінні в зовнішній функції були захоплені (закриті або прив'язані) внутрішньою функцією. Тому й термін **замикання**. Сама концепція достатньо проста й досить інтуїтивна. 20 | 21 | Тепер найцікавіша частина: внутрішня функція може мати доступ до змінних зовнішнього контексту *навіть після повернення зовнішньої функції*. Це сталося через те, що змінні все ще прив'язані внутрішньою функцією і не залежать від зовнішньої функції. Знову ж таки, розглянемо приклад: 22 | 23 | ```ts 24 | function outerFunction(arg) { 25 | var variableInOuterFunction = arg; 26 | return function() { 27 | console.log(variableInOuterFunction); 28 | } 29 | } 30 | 31 | var innerFunction = outerFunction("hello closure!"); 32 | 33 | // Note the outerFunction has returned 34 | innerFunction(); // logs hello closure! 35 | ``` 36 | 37 | ### Причина, чому це чудово 38 | Це дозволяє легко компонувати об'єкти, наприклад, за допомогою шаблону розкривання модуля (revealing module pattern): 39 | 40 | ```ts 41 | function createCounter() { 42 | let val = 0; 43 | return { 44 | increment() { val++ }, 45 | getVal() { return val } 46 | } 47 | } 48 | 49 | let counter = createCounter(); 50 | counter.increment(); 51 | console.log(counter.getVal()); // 1 52 | counter.increment(); 53 | console.log(counter.getVal()); // 2 54 | ``` 55 | 56 | На високому рівні це також те, що робить можливим існування чогось подібного до Node.js (не хвилюйтеся, якщо це наразі не зрозуміло. Зрозуміння прийде з часом 🌹): 57 | 58 | ```ts 59 | // Pseudo code to explain the concept 60 | server.on(function handler(req, res) { 61 | loadData(req.id).then(function(data) { 62 | // the `res` has been closed over and is available 63 | res.send(data); 64 | }) 65 | }); 66 | ``` 67 | -------------------------------------------------------------------------------- /docs/javascript/equality.md: -------------------------------------------------------------------------------- 1 | ## Порівняння 2 | 3 | Одна річ, на яку потрібно звернути увагу в JavaScript, це різниця між `==` та `===`. Оскільки JavaScript намагається бути стійким до помилок програмування, `==` намагається автоматично конвертувати типи між двома змінними, наприклад, конвертує рядок в число, щоб ви могли порівняти з числом, як показано нижче: 4 | 5 | ```js 6 | console.log(5 == "5"); // true , TS Error 7 | console.log(5 === "5"); // false , TS Error 8 | ``` 9 | 10 | Однак, вибір, який робить JavaScript, не завжди є ідеальним. Наприклад, у наведеному нижче прикладі перше твердження є хибним, оскільки `""` та `"0"` - це обидва рядки (string) і, очевидно, не є рівними. Однак у другому випадку як `0`, так і пустий рядок (`""`) є ложними значеннями (тобто поводяться як `false`) і, отже, вони рівні з точки зору `==`. У обох випадках твердження є хибними, коли використовується `===`. 11 | 12 | ```js 13 | console.log("" == "0"); // false 14 | console.log(0 == ""); // true 15 | 16 | console.log("" === "0"); // false 17 | console.log(0 === ""); // false 18 | ``` 19 | 20 | > Зауважте, що `string == number` та `string === number` обидва є помилками на етапі компіляції в TypeScript, тому зазвичай вам не потрібно хвилюватися про це. 21 | 22 | Аналогічно до `==` проти `===`, існує також `!=` проти `!==`. 23 | 24 | Тому порада: завжди використовуйте `===` і `!==`, за винятком перевірок на значення null, про які ми розповімо пізніше. 25 | 26 | ## Структурне порівняння 27 | Якщо ви хочете порівняти два об'єкти на структурну рівність, оператори `==`/`===` ***не є достатніми***. Наприклад: 28 | 29 | ```js 30 | console.log({a:123} == {a:123}); // False 31 | console.log({a:123} === {a:123}); // False 32 | ``` 33 | Для здійснення таких перевірок використовуйте пакет npm [deep-equal](https://www.npmjs.com/package/deep-equal), наприклад: 34 | 35 | ```js 36 | import * as deepEqual from "deep-equal"; 37 | 38 | console.log(deepEqual({a:123},{a:123})); // True 39 | ``` 40 | 41 | Однак, досить часто вам не потрібно глибоке порівняння, і все, що вам дійсно потрібно, - це перевірка за допомогою якогось `id`, наприклад: 42 | 43 | ```ts 44 | type IdDisplay = { 45 | id: string, 46 | display: string 47 | } 48 | const list: IdDisplay[] = [ 49 | { 50 | id: 'foo', 51 | display: 'Foo Select' 52 | }, 53 | { 54 | id: 'bar', 55 | display: 'Bar Select' 56 | }, 57 | ] 58 | 59 | const fooIndex = list.map(i => i.id).indexOf('foo'); 60 | console.log(fooIndex); // 0 61 | ``` 62 | -------------------------------------------------------------------------------- /docs/javascript/references.md: -------------------------------------------------------------------------------- 1 | ## Посилання (references) 2 | 3 | Окрім літералів, будь-який об'єкт у JavaScript (включаючи функції, масиви, regexp тощо) є посиланням. Це означає наступне 4 | 5 | ### Мутації є у всіх посилання 6 | 7 | ```js 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 | ### Порівнення при посиланнях 16 | У JavaScript, при порівнянні об'єктів або масивів оператор рівності (== або ===) порівнює посилання, а не фактичний зміст об'єктів. Це означає, що два об'єкти або масиви вважаються рівними лише тоді, коли вони посилаються на ту саму область пам'яті. 17 | 18 | ```js 19 | var foo = {}; 20 | var bar = foo; // bar is a reference 21 | var baz = {}; // baz is a *new object* distinct from `foo` 22 | 23 | console.log(foo === bar); // true 24 | console.log(foo === baz); // false 25 | ``` 26 | -------------------------------------------------------------------------------- /docs/javascript/this.md: -------------------------------------------------------------------------------- 1 | ## this 2 | 3 | Будь-який доступ до ключового слова `this` у функції контролюється способом виклику функції. Його зазвичай називають "контекстом виклику". 4 | 5 | Приклад: 6 | 7 | ```ts 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 | Тому будьте обережні з використанням `this`. Якщо ви хочете від'єднати `this` у класі від контексту виклику, використовуйте функцію-стрілку, [докладніше про це пізніше][arrow]. 20 | 21 | [arrow]:../arrow-functions.md 22 | -------------------------------------------------------------------------------- /docs/javascript/truthy.md: -------------------------------------------------------------------------------- 1 | ## Істинність (тruthy) 2 | 3 | JavaScript має концепцію "істинності" (`truthy`), тобто речей, які оцінюються як `true` в певних контекстах (наприклад, в умовах оператора `if` та логічних операторах `&&` та `||`). Наступні речі є істинними в JavaScript. Наприклад, будь-яке число, крім `0`, наприклад: 4 | 5 | ```ts 6 | if (123) { // Will be treated like `true` 7 | console.log('Any number other than 0 is truthy'); 8 | } 9 | ``` 10 | 11 | Те, що не є істиною (truthy), зветься хибним (falsy). 12 | 13 | Ось зручна таблиця для вашої довідки: 14 | 15 | | Значення | *falsy* | *truthy* | 16 | |-----------------|--------------------------|--------------------------| 17 | | `boolean` | `false` | `true` | 18 | | `string` | `''` (empty string) | будь-який string | 19 | | `number` | `0` `NaN` | будь-який number | 20 | | `null` | завжди | ніколи | 21 | | `undefined` | завжди | ніколи | 22 | | Будь-який Object, в тому числі порожній `{}`,`[]` | ніколи | завжди | 23 | 24 |
25 | 26 | ### Бути явним: 27 | 28 | > Шаблон !!: 29 | 30 | Досить часто буває корисно чітко вказати, що ви хочете розглядати значення як `boolean` і перетворити його в *правильне булеве значення* (одне з `true`|`false`). Ви можете легко перетворити значення на істинний булевий вираз, додавши до нього префікс `!!`, наприклад `!!foo`. Просто `!` використовується *двічі*. Перший `!` перетворює змінну (у цьому випадку `foo`) на булеве значення, але інвертує логіку (*truthy* -`!`> `false`, *falsy* -`!`> `true`). Другий перемикає її знову, щоб відповідати природі початкового об'єкта (наприклад, *truthy* -`!`> `false` -`!`> `true`). 31 | 32 | 33 | Цей шаблон часто використовується в багатьох місцях, наприклад: 34 | 35 | ```js 36 | // Direct variables 37 | const hasName = !!name; 38 | 39 | // As members of objects 40 | const someObj = { 41 | hasName: !!name 42 | } 43 | 44 | // e.g. in ReactJS JSX 45 | {!!someName &&
{someName}
} 46 | ``` 47 | -------------------------------------------------------------------------------- /docs/jsx/others.md: -------------------------------------------------------------------------------- 1 | # JSX без React 2 | 3 | [![DesignTSX](https://raw.githubusercontent.com/basarat/typescript-book/master/images/designtsx-banner.png)](https://designtsx.com) 4 | 5 | TypeScript надає вам можливість використовувати щось інше, крім React, з JSX у безпечний для типів спосіб. Нижче перераховані пункти, що стосуються налаштування, проте зверніть увагу, що це для досвідчених авторів фреймворків інтерфейсів: 6 | 7 | * Ви можете вимкнути генерацію коду у стилі `react`, встановивши опцію `"jsx": "preserve"`. Це означає, що JSX буде виводитись *як є*, а потім ви можете використовувати власний транспілятор для трансляції частин JSX. 8 | * Використання глобального модуля `JSX`: 9 | * Ви можете контролювати, які HTML-теги доступні і як вони перевіряються на тип налаштовуючи члени інтерфейсу `JSX.IntrinsicElements`. 10 | * При використанні компонентів: 11 | * Ви можете керувати тим, який `клас` має бути успадкований компонентами, налаштовуючи дефолтний інтерфейс `interface ElementClass extends React.Component { }`. 12 | * Ви можете керувати тим, яка властивість використовується для перевірки типу атрибутів (за дефолтом це `props`) налаштувавши оголошення `declare module JSX { interface ElementAttributesProperty { props: {}; } }`. 13 | 14 | ## `jsxFactory` 15 | 16 | Передача `--jsxFactory <Ім'я фабрики JSX>` разом з `--jsx react` дозволяє використовувати іншу фабрику JSX, відмінну від стандартної `React`. 17 | 18 | Ім'я нової фабрики буде використовуватися для виклику функцій `createElement`. 19 | 20 | ### Приклад 21 | 22 | ```ts 23 | import {jsxFactory} from "jsxFactory"; 24 | 25 | var div =
Hello JSX!
26 | ``` 27 | 28 | Скомпільовано з: 29 | 30 | ```shell 31 | tsc --jsx react --reactNamespace jsxFactory --m commonJS 32 | ``` 33 | 34 | Результатом є: 35 | 36 | ```js 37 | "use strict"; 38 | var jsxFactory_1 = require("jsxFactory"); 39 | var div = jsxFactory_1.jsxFactory.createElement("div", null, "Hello JSX!"); 40 | ``` 41 | 42 | ## `jsx` pragma 43 | 44 | Ви навіть можете вказати різні `jsxFactory` для кожного файлу за допомогою `jsxPragma`, наприклад. 45 | 46 | ```js 47 | /** @jsx jsxFactory */ 48 | import {jsxFactory} from "jsxFactory"; 49 | 50 | var div =
Hello JSX!
51 | ``` 52 | 53 | За допомогою опції `--jsx react`, цей файл буде генерувати використання фабрики, вказаної в pragma JSX: 54 | 55 | ```js 56 | "use strict"; 57 | var jsxFactory_1 = require("jsxFactory"); 58 | var div = jsxFactory_1.jsxFactory.createElement("div", null, "Hello JSX!"); 59 | ``` 60 | -------------------------------------------------------------------------------- /docs/jsx/tsx.md: -------------------------------------------------------------------------------- 1 | # Підтримка JSX 2 | 3 | [![DesignTSX](https://raw.githubusercontent.com/basarat/typescript-book/master/images/designtsx-banner.png)](https://designtsx.com) 4 | 5 | TypeScript підтримує транскрипцію JSX та аналіз коду. Якщо ви не знайомі з JSX, ось уривок з документації [офіційний сайт](https://facebook.github.io/jsx/): 6 | 7 | > JSX - це розширення синтаксису, схожого на XML, для ECMAScript без визначених семантик. Він НЕ призначений для реалізації двигунами або браузерами. Це НЕ пропозиція включити JSX до самого стандарту ECMAScript. Він призначений для використання різними попередніми обробниками (транспіляторами) для перетворення цих токенів на стандартний ECMAScript. 8 | 9 | Мотивація JSX полягає в тому, щоб дозволити користувачам писати HTML-подібні представлення *на JavaScript*, щоб ви могли: 10 | 11 | * Перевіряти тип представлення тим самим кодом, який буде перевіряти ваш JavaScript 12 | * Мати уявлення про контекст, в якому він буде працювати (наприклад, зміцнювати *controller-view* зв'язок в традиційній архітектурі MVC). 13 | * Перевикористовувати шаблони JavaScript для обслуговування HTML, наприклад `Array.prototype.map`, `?:`, `switch` і т. д., замість створення нових (і, ймовірно, погано типізованих) альтернатив. 14 | 15 | Це зменшує ймовірність помилок і підвищує підтримуваність вашого інтерфейсу користувача. Основним користувачем JSX на даний момент є [ReactJS від Facebook](http://facebook.github.io/react/). Ми будемо обговорювати використання JSX саме з ReactJS. 16 | -------------------------------------------------------------------------------- /docs/options/intro.md: -------------------------------------------------------------------------------- 1 | # Convenience vs. Soundness 2 | 3 | Є кілька речей, які TypeScript не дозволяє вам робити з коробки, наприклад. використовуючи змінну, яка *ніколи не оголошується* (звичайно, ви можете використовувати *файл декларації* для зовнішніх систем). 4 | 5 | Тим не менш, традиційні мови програмування мають жорстку межу між тим, що дозволено і заборонено системою типів. TypeScript відрізняється тим, що він дає вам контроль над тим, де розмістити повзунок. Це дійсно для того, щоб дозволити вам використовувати JavaScript, який ви знаєте і любите, з такою безпечністю, як **Ви** хочете. Існує багато параметрів компілятора для керування саме цим повзунком, тому давайте подивимося. 6 | 7 | ## Boolean Options 8 | 9 | `compilerOptions`, які є `boolean`, можна вказати як `compilerOptions` у `tsconfig.json`: 10 | 11 | ```json 12 | { 13 | "compilerOptions": { 14 | "someBooleanOption": true 15 | } 16 | } 17 | ``` 18 | 19 | чи в командному рядку 20 | 21 | ```sh 22 | tsc --someBooleanOption 23 | ``` 24 | 25 | > Усе це за замовчуванням `false`. 26 | 27 | Натисніть [тут](https://www.typescriptlang.org/docs/handbook/compiler-options.html), щоб переглянути всі параметри компілятора. 28 | -------------------------------------------------------------------------------- /docs/options/noImplicitAny.md: -------------------------------------------------------------------------------- 1 | # noImplicitAny 2 | 3 | Є деякі речі, про які неможливо зробити висновок, або їх висновок може призвести до несподіваних помилок. Гарним прикладом є аргументи функції. Якщо ви не анотуєте їх, незрозуміло, що має бути дійсним, а що ні. 4 | 5 | ```ts 6 | function log(someArg) { 7 | sendDataToServer(someArg); 8 | } 9 | 10 | // Який аргумент вірний а який ні? 11 | log(123); 12 | log('hello world'); 13 | ``` 14 | 15 | Отже, якщо ви не анотуєте якийсь аргумент функції, TypeScript припускає `any` і йде далі. По суті, це вимикає перевірку типу для таких випадків, чого очікував би розробник JavaScript. Але це може застати людей, які хочуть високої безпеки, зненацька. Таким чином, існує опція `noImplicitAny`, яка після ввімкнення позначатиме випадки, коли тип не можна визначити, наприклад. 16 | 17 | ```ts 18 | function log(someArg) { // Error : someArg has an implicit `any` type 19 | sendDataToServer(someArg); 20 | } 21 | ``` 22 | 23 | Звичайно, ви можете продовжити і описати: 24 | 25 | ```ts 26 | function log(someArg: number) { 27 | sendDataToServer(someArg); 28 | } 29 | ``` 30 | 31 | І якщо ви справді бажаєте *нульової безпеки*, ви можете позначити його *явно* як `any`: 32 | 33 | ```ts 34 | function log(someArg: any) { 35 | sendDataToServer(someArg); 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/project/compilation-context.md: -------------------------------------------------------------------------------- 1 | ## Compilation Context 2 | Контекст компіляції — це, по суті, просто модний термін для групування файлів, які TypeScript читати та аналізуватиме, щоб визначити, що є дійсним, а що ні. Разом з інформацією про те, які є файли, контекст компіляції містить інформацію про *які параметри компілятора* використовуються. Чудовий спосіб визначити це логічне групування (ми також любимо використовувати термін *project*) — це використовувати файл `tsconfig.json`. 3 | -------------------------------------------------------------------------------- /docs/project/declarationspaces.md: -------------------------------------------------------------------------------- 1 | ## Declaration Spaces 2 | 3 | У TypeScript є два простори оголошень: простір оголошення *variable* і простір оголошення *type*. Ці поняття досліджуються нижче. 4 | 5 | ### Type Declaration Space 6 | Простір оголошення типу містить матеріал, який можна використовувати як анотацію типу. Наприклад нижче наведено кілька декларацій типів: 7 | 8 | ```ts 9 | class Foo {}; 10 | interface Bar {}; 11 | type Bas = {}; 12 | ``` 13 | Це означає, що ви можете використовувати `Foo`, `Bar`, `Bas` як анотацію типу. Наприклад: 14 | 15 | ```ts 16 | var foo: Foo; 17 | var bar: Bar; 18 | var bas: Bas; 19 | ``` 20 | 21 | Зауважте, що навіть якщо у вас є `інтерфейс`, *ви не можете використовувати її як змінну*, оскільки вона не сприяє *простору оголошення змінних*. Це показано нижче: 22 | 23 | ```ts 24 | interface Bar {}; 25 | var bar = Bar; // ERROR: "cannot find name 'Bar'" 26 | ``` 27 | 28 | Причина, чому він каже `не вдається знайти ім’я`, полягає в тому, що ім’я `Bar` *не визначено* у *просторі оголошення змінної*. Це підводить нас до наступної теми «Простір оголошення змінних». 29 | 30 | ### Variable Declaration Space 31 | Простір оголошення змінної містить матеріал, який можна використовувати як змінну. Ми побачили, що наявність `class Foo` вносить тип `Foo` в простір оголошення *type*. Вгадай що? Він також додає *змінну* `Foo` до простору оголошення *змінної*, як показано нижче: 32 | 33 | ```ts 34 | class Foo {}; 35 | var someVar = Foo; 36 | var someOtherVar = 123; 37 | ``` 38 | Це чудово, оскільки іноді ви хочете передати класи як змінні. Пам'ятайте, що: 39 | 40 | * ми не могли використовувати щось на зразок `інтерфейсу`, який є *тільки* у просторі оголошення *type* як змінну. 41 | 42 | Подібним чином те, що ви оголошуєте за допомогою `var`, знаходиться *тільки* в просторі оголошення *variable* і не може використовуватися як анотація типу: 43 | 44 | ```ts 45 | var foo = 123; 46 | var bar: foo; // ERROR: "cannot find name 'foo'" 47 | ``` 48 | Причина, чому написано `не вдається знайти ім’я`, полягає в тому, що ім’я `foo` *не визначено* у просторі оголошення *type*. 49 | -------------------------------------------------------------------------------- /docs/project/files.md: -------------------------------------------------------------------------------- 1 | ## Which files? 2 | 3 | Використовуйте `include` і `exclude`, щоб указати файли / папки / globs. Наприклад: 4 | 5 | 6 | ```json 7 | { 8 | "include":[ 9 | "./folder" 10 | ], 11 | "exclude":[ 12 | "./folder/**/*.spec.ts", 13 | "./folder/someSubFolder" 14 | ] 15 | } 16 | ``` 17 | 18 | ### Globs 19 | 20 | * Для глобальних: `**/*` (наприклад, приклад використання `somefolder/**/*`) означає всі папки та будь-які файли (припускаються розширення `.ts`/`.tsx` і якщо `allowJs:true ` так буде `.js`/`.jsx`) 21 | 22 | ### `files` option 23 | Крім того, ви можете використовувати `files`, щоб бути явним: 24 | 25 | ```json 26 | { 27 | "files":[ 28 | "./some/file.ts" 29 | ] 30 | } 31 | ``` 32 | 33 | Але це не рекомендується, оскільки ви повинні постійно оновлювати його. Натомість використовуйте `include`, щоб просто додати папку, що містить. 34 | -------------------------------------------------------------------------------- /docs/project/globals.md: -------------------------------------------------------------------------------- 1 | # global.d.ts 2 | 3 | Ми обговорювали *global* та *file* модулі під час розгляду [проектів](./modules.md) і рекомендували використовувати файлові модулі та не забруднювати глобальний простір імен. 4 | 5 | Тим не менше, якщо у вас є розробники-початківці TypeScript, ви можете надати їм файл `global.d.ts` для розміщення інтерфейсів/типів у глобальному просторі імен, щоб зробити деякі *types* просто *magically* доступним для використання в *цілоту* вашему коді TypeScript. 6 | 7 | Іншим варіантом використання файлу `global.d.ts` є оголошення констант часу компіляції, які Webpack додає у вихідний код за допомогою стандартного [DefinePlugin](https://webpack.js.org/plugins/define -plugin/) плагін. 8 | 9 | ```ts 10 | declare const BUILD_MODE_PRODUCTION: boolean; // can be used for conditional compiling 11 | declare const BUILD_VERSION: string; 12 | ``` 13 | 14 | > Для будь-якого коду, який збирається генерувати *JavaScript*, ми наполегливо рекомендуємо використовувати *file modules* та використовувати лише `global.d.ts` для оголошення констант часу компіляції та/або для розширення стандартних декларацій типів, оголошених у `lib.d.ts`. 15 | 16 | * Бонус: файл `global.d.ts` також добре підходить для швидкого `declare module "some-library-you-dont-care-to-get-defs-for";` під час міграції JS до TS. 17 | -------------------------------------------------------------------------------- /docs/project/modules.md: -------------------------------------------------------------------------------- 1 | ## Modules 2 | 3 | ### Global Module 4 | 5 | За замовчуванням, коли ви починаєте вводити код у новому файлі TypeScript, ваш код знаходиться в *глобальному* просторі імен. Як демонстрацію розглянемо файл `foo.ts`: 6 | 7 | ```ts 8 | var foo = 123; 9 | ``` 10 | 11 | Якщо ви тепер створите *новий* файл `bar.ts` у тому самому проекті, вам буде *дозволено* системою типів TypeScript використовувати змінну `foo` так, якби вона була доступна глобально: 12 | 13 | ```ts 14 | var bar = foo; // allowed 15 | ``` 16 | Зайве говорити, що мати глобальний простір імен небезпечно, оскільки це відкриває ваш код для конфліктів імен. Ми рекомендуємо використовувати файлові модулі, які представлені далі. 17 | 18 | ### File Module 19 | Також називаються *зовнішніми модулями*. Якщо у вас є «імпорт» або «експорт» на кореневому рівні файлу TypeScript, тоді в цьому файлі створюється *локальна* область. Отже, якщо ми змінимо попередній `foo.ts` на такий (зверніть увагу на використання `export`): 20 | 21 | ```ts 22 | export var foo = 123; 23 | ``` 24 | 25 | Ми більше не матимемо `foo` у глобальному просторі імен. Це можна продемонструвати, створивши новий файл `bar.ts` наступним чином: 26 | ```ts 27 | var bar = foo; // ERROR: "cannot find name 'foo'" 28 | ``` 29 | 30 | Якщо ви хочете використовувати матеріали з `foo.ts` у `bar.ts` *вам потрібно явно імпортувати це*. Це показано в оновленому `bar.ts` нижче: 31 | 32 | ```ts 33 | import { foo } from "./foo"; 34 | var bar = foo; // allowed 35 | ``` 36 | Використання `import` у `bar.ts` не тільки дає змогу вводити матеріали з інших файлів, але також позначає файл `bar.ts` як *модуль*, а отже, оголошення в `bar.ts` не також не забруднювати глобальний простір імен. 37 | 38 | Те, що JavaScript генерується з даного файлу TypeScript, який використовує зовнішні модулі, керується прапором компілятора під назвою `module`. 39 | -------------------------------------------------------------------------------- /docs/project/namespaces.md: -------------------------------------------------------------------------------- 1 | ## Namespaces 2 | Простори імен надають вам зручний синтаксис навколо загального шаблону, який використовується в JavaScript: 3 | 4 | ```ts 5 | (function(something) { 6 | 7 | something.foo = 123; 8 | 9 | })(something || (something = {})) 10 | ``` 11 | 12 | В основному `something || (something = {})` дозволяє анонімній функції `function(something) {}` *add stuff to an existing object* (`something`) або *start a new object then add stuff to that object* (`|| (something = {})`). Це означає, що ви можете мати два таких блоки, розділені деякою межею виконання: 13 | ```ts 14 | (function(something) { 15 | 16 | something.foo = 123; 17 | 18 | })(something || (something = {})) 19 | 20 | console.log(something); // {foo:123} 21 | 22 | (function(something) { 23 | 24 | something.bar = 456; 25 | 26 | })(something || (something = {})) 27 | 28 | console.log(something); // {foo:123, bar:456} 29 | 30 | ``` 31 | 32 | Це зазвичай використовується в JavaScript, щоб переконатися, що матеріал не просочується в глобальний простір імен. З модулями на основі файлів вам не потрібно турбуватися про це, але шаблон все ще корисний для *logical grouping* купи функцій. Тому TypeScript надає ключове слово `namespace` для групування, наприклад: 33 | 34 | ```ts 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 | Ключове слово `namespace` генерує той самий JavaScript, який ми бачили раніше: 50 | 51 | ```ts 52 | (function (Utility) { 53 | 54 | // Add stuff to Utility 55 | 56 | })(Utility || (Utility = {})); 57 | ``` 58 | 59 | Варто зауважити, що простори імен можуть бути вкладеними, тому ви можете робити такі речі, як `namespace Utility.Messaging`, щоб вкладати простір імен `Messaging` у `Utility`. 60 | 61 | Для більшості проектів ми рекомендуємо використовувати зовнішні модулі та `namespace` для швидких демонстрацій і перенесення старого коду JavaScript. 62 | -------------------------------------------------------------------------------- /docs/project/project.md: -------------------------------------------------------------------------------- 1 | # Project 2 | 3 | Щоб створити успішний проект за допомогою TypeScript, вам потрібно розуміти різні доступні функції мови організації проекту. У цьому розділі ми розглянемо «контекст компіляції», простори оголошень і модулі. 4 | -------------------------------------------------------------------------------- /docs/quick/nodejs.md: -------------------------------------------------------------------------------- 1 | # TypeScript with Node.js 2 | TypeScript має *first class* підтримку Node.js з самого початку. Ось як налаштувати швидкий проект Node.js: 3 | 4 | > Примітка: багато з цих кроків насправді є звичайними кроками налаштування Node.js 5 | 6 | 1. Встановіть `package.json` в проект Node.js. Швидкий шлях: `npm init -y` 7 | 1. Додайте TypeScript (`npm install typescript --save-dev`) 8 | 1. Додайте `node.d.ts` (`npm install @types/node --save-dev`) 9 | 1. Ініціалізуйте `tsconfig.json` для параметрів TypeScript з кількома ключовими параметрами у вашому tsconfig.json (`npx tsc --init --rootDir src --outDir lib --esModuleInterop --resolveJsonModule --lib es6,dom --module commonjs`) 10 | 11 | Це воно! Запустіть свою IDE (наприклад, `code .`) і спробуйте. Тепер ви можете використовувати всі вбудовані модулі вузлів (наприклад, `import * as fs from 'fs';`) з усією безпекою та ергономікою розробника TypeScript! 12 | 13 | Весь ваш код TypeScript міститься в `src`, а згенерований JavaScript — у `lib`. 14 | 15 | ## Bonus: Live compile + run 16 | * Додайте `ts-node`, який ми будемо використовувати для живої компіляції + запуску у вузлі (`npm install ts-node --save-dev`) 17 | * Додайте `nodemon`, який буде викликати `ts-node` щоразу, коли файл буде змінено (`npm install nodemon --save-dev`) 18 | 19 | Тепер просто додайте `script` до свого `package.json` на основі запису вашої програми, наприклад, припускаючи його `index.ts`: 20 | 21 | ```json 22 | "scripts": { 23 | "start": "npm run build:live", 24 | "build": "tsc -p .", 25 | "build:live": "nodemon --watch 'src/**/*.ts' --exec \"ts-node\" src/index.ts" 26 | }, 27 | ``` 28 | 29 | Тепер ви можете запустити `npm start` і під час редагування `index.ts`: 30 | 31 | * nodemon повторно виконує свою команду (ts-node) 32 | * ts-node transpiles автоматично збирає tsconfig.json і встановлену версію TypeScript, 33 | * ts-node запускає вихідний JavaScript через Node.js. 34 | 35 | І коли ви будете готові розгорнути свою програму JavaScript, запустіть `npm run build`. 36 | 37 | 38 | ## Bonus points 39 | 40 | Такі модулі NPM чудово працюють із browserify (за допомогою tsify) або webpack (за допомогою ts-loader). 41 | -------------------------------------------------------------------------------- /docs/rest-parameters.md: -------------------------------------------------------------------------------- 1 | ### Rest Parameters 2 | 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. 3 | 4 | ```ts 5 | function iTakeItAll(first, second, ...allOthers) { 6 | console.log(allOthers); 7 | } 8 | iTakeItAll('foo', 'bar'); // [] 9 | iTakeItAll('foo', 'bar', 'bas', 'qux'); // ['bas','qux'] 10 | ``` 11 | 12 | Rest parameters can be used in any function be it `function`/`()=>`/`class member`. 13 | -------------------------------------------------------------------------------- /docs/staging/async-await.md: -------------------------------------------------------------------------------- 1 | ### Async - Await 2 | -------------------------------------------------------------------------------- /docs/staging/generators.md: -------------------------------------------------------------------------------- 1 | ### Generators 2 | Генератори, які також називаються `функцією *`, дозволяють створювати функції, виконання яких можна призупинити, а потім відновити, зберігаючи стан між переходами пауза-відновлення. Значення, яке повертає генератор, називається «ітератором», і його можна використовувати для керування цим переходом «пауза-відновлення». 3 | 4 | Ось простий приклад функції генератора, яка генерує *нескінченний* список цілих чисел. 5 | 6 | ```ts 7 | function* wholeNumbers() { 8 | var current = 0; 9 | while(true) { 10 | yield current++; 11 | } 12 | } 13 | ``` 14 | 15 | Контекстне ключове слово `yield` використовується для повернення керування від генератора (ефективно призупиняючи виконання функції) разом із необов’язковим значенням (тут `current`). Ви можете отримати доступ до цього значення за допомогою функції-члена `iterator.next()`, це показано нижче: 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 | Тепер, коли ви бачили `function*`, `yield` і `.next()`, ми можемо копати глибше. 32 | 33 | #### Catching Errors 34 | Будь-які помилки, викинуті генератором (навмисно за допомогою `throw` або випадково через помилку), можуть бути перехоплени за допомогою `try/catch` так само, як і звичайне виконання функції. Це показано нижче: 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 | Ітератор, повернутий функцією генератора, також можна використовувати для керування станом *всередині* функції генератора. 60 | 61 | // TODO: приклад 62 | -------------------------------------------------------------------------------- /docs/state/mobx.md: -------------------------------------------------------------------------------- 1 | ## MobX 2 | 3 | > [PRO Egghead course on MobX TypeScript React](https://egghead.io/courses/develop-react-applications-with-mobx-and-typescript) 4 | 5 | -------------------------------------------------------------------------------- /docs/styleguide/sample.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var formatting; 3 | (function (formatting) { 4 | var FooVar; 5 | function BarFunc() { } 6 | })(formatting || (formatting = {})); 7 | var asdfasdf; 8 | (function (asdfasdf) { 9 | var Foo = (function () { 10 | function Foo() { 11 | } 12 | Foo.prototype.baz = function () { }; 13 | return Foo; 14 | }()); 15 | })(asdfasdf || (asdfasdf = {})); 16 | -------------------------------------------------------------------------------- /docs/styleguide/sample.ts: -------------------------------------------------------------------------------- 1 | export var test; 2 | 3 | namespace formatting { 4 | var FooVar; 5 | function BarFunc() { } 6 | } 7 | 8 | namespace asdfasdf { 9 | class Foo { 10 | bar: number; 11 | baz() { } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /docs/styleguide/tsconfig.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /docs/testing/intro.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | TypeScript можна використовувати з будь-якою платформою для тестування JavaScript. У гіршому випадку ви завжди можете виконати просте перетворення `TypeScript -> JavaScript` і йти своїм шляхом. 3 | 4 | Проте в цьому розділі перегляньте варіанти, які нам дуже сподобалися 🌹 5 | -------------------------------------------------------------------------------- /docs/tips/barrel.md: -------------------------------------------------------------------------------- 1 | ## Barrel 2 | 3 | Barrel це спосіб згортання експорту з кількох модулів в один зручний модуль. Сам барель є файлом модуля, який повторно експортує вибрані експорти інших модулів. 4 | 5 | Уявіть наступну структуру класів у бібліотеці: 6 | 7 | ```ts 8 | // demo/foo.ts 9 | export class Foo {} 10 | 11 | // demo/bar.ts 12 | export class Bar {} 13 | 14 | // demo/baz.ts 15 | export class Baz {} 16 | ``` 17 | Без barrel користувач потребує зробити 3 import: 18 | 19 | ```ts 20 | import { Foo } from '../demo/foo'; 21 | import { Bar } from '../demo/bar'; 22 | import { Baz } from '../demo/baz'; 23 | ``` 24 | 25 | Замість цього можно використовувати barrel `demo/index.ts` який реекспортує: 26 | 27 | ```ts 28 | // demo/index.ts 29 | export * from './foo'; // re-export all of its exports 30 | export * from './bar'; // re-export all of its exports 31 | export * from './baz'; // re-export all of its exports 32 | ``` 33 | 34 | Зараз можно використати простий синтансис: 35 | 36 | ```ts 37 | import { Foo, Bar, Baz } from '../demo'; // demo/index.ts is implied 38 | ``` 39 | 40 | ### Named exports 41 | Іменований експорт. 42 | 43 | Замість експорту всього через `*`, ви можете вибрати модуль для експорту по назві. Наприклад, `baz.ts` має функції: 44 | 45 | ```ts 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 | Якщо ви не хочете експортовать `getBaz` / `setBaz` з demoнатомість ви можете помістити їх у змінну, імпортувавши їх у назву та експортувавши цю назву, як показано нижче: 58 | 59 | ```ts 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 | Зараз ви маєте такий імпорт: 69 | 70 | ```ts 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 | -------------------------------------------------------------------------------- /docs/tips/build-toggles.md: -------------------------------------------------------------------------------- 1 | ## Build Toggles 2 | Перемикачі побудови 3 | 4 | Зазвичай проекти JavaScript перемикаються залежно від того, де вони виконуються. Ви можете зробити це досить легко за допомогою webpack, оскільки він підтримує *усунення мертвого коду* на основі змінних середовища. 5 | 6 | Ви можете додати це у ваш `package.json` `scripts`: 7 | 8 | ```json 9 | "build:test": "webpack -p --config ./src/webpack.config.js", 10 | "build:prod": "webpack -p --define process.env.NODE_ENV='\"production\"' --config ./src/webpack.config.js", 11 | ``` 12 | 13 | Звичайно, я припускаю, що у вас є `npm install webpack --save-dev`. Зараз ви можете використовувати `npm run build:test`. 14 | 15 | Використовувати цю змінну також дуже просто: 16 | 17 | ```ts 18 | /** 19 | * This interface makes sure we don't miss adding a property to both `prod` and `test` 20 | */ 21 | interface Config { 22 | someItem: string; 23 | } 24 | 25 | /** 26 | * We only export a single thing. The config. 27 | */ 28 | export let config: Config; 29 | 30 | /** 31 | * `process.env.NODE_ENV` definition is driven from webpack 32 | * 33 | * The whole `else` block will be removed in the emitted JavaScript 34 | * for a production build 35 | */ 36 | if (process.env.NODE_ENV === 'production') { 37 | config = { 38 | someItem: 'prod' 39 | } 40 | console.log('Running in prod'); 41 | } else { 42 | config = { 43 | someItem: 'test' 44 | } 45 | console.log('Running in test'); 46 | } 47 | ``` 48 | 49 | > Ви використовуєте `process.env.NODE_ENV` просто тому, що це традиційно у багатьох бібліотеках JavaScript, наприклад, `React`. 50 | -------------------------------------------------------------------------------- /docs/tips/classesAreUseful.md: -------------------------------------------------------------------------------- 1 | ## Classes Are Useful 2 | Класи корисні 3 | 4 | Дуже часто зустрічається така структура: 5 | 6 | ```ts 7 | function foo() { 8 | let someProperty; 9 | 10 | // інший код ініціалізації 11 | 12 | function someMethod() { 13 | // робота з властивостями `someProperty` 14 | // та інакший код 15 | } 16 | // можливо інші методи 17 | 18 | return { 19 | someMethod, 20 | // можливо інші методи 21 | }; 22 | } 23 | ``` 24 | 25 | Це відомо як *шаблон розкриваючого модуля* (*revealing module pattern*) і досить поширений у JavaScript (використовує переваги замикання JavaScript). 26 | 27 | якщо ви використовуєте [*file modules* (що ви дійсно повинні робити, оскільки глобальний скоп - це погано)](../project/modules.md) тоді *your file is effectively the same* (ваш файл фактично той самий). Однак є занадто багато випадків, коли люди пишуть такий код: 28 | 29 | ```ts 30 | let someProperty; 31 | 32 | function foo() { 33 | 34 | // інший код ініціалізації 35 | } 36 | foo(); // код ініціалізації 37 | 38 | someProperty = 123; // ще код ініціалізації 39 | 40 | // Деякі службові функції не експортовано 41 | 42 | // після 43 | export function someMethod() { 44 | 45 | } 46 | ``` 47 | 48 | Незважаючи на те, що я не є великим шанувальником успадкування *я вважаю, що дозвіл використовувати класи допомагає краще організувати свій код*. Той же розробник інтуїтивно написав би наступне: 49 | 50 | ```ts 51 | class Foo { 52 | public someProperty; 53 | 54 | constructor() { 55 | // ініціалізація 56 | } 57 | 58 | public someMethod() { 59 | // код 60 | } 61 | 62 | private someUtility() { 63 | // код 64 | } 65 | } 66 | 67 | export = new Foo(); 68 | ``` 69 | 70 | І це не лише розробники, створення інструментів для розробників, які забезпечують чудову візуалізацію класів, є набагато поширенішим, і вашій команді потрібно розуміти та підтримувати на один шаблон менше. 71 | 72 | > PS: На мій погляд, немає нічого поганого в *неглибоких* ієрархіях класів, якщо вони забезпечують значне повторне використання та зменшення обсягу. 73 | -------------------------------------------------------------------------------- /docs/tips/create-arrays.md: -------------------------------------------------------------------------------- 1 | ## Creating arrays 2 | Створення масивів 3 | 4 | Створити порожній масив дуже легко: 5 | 6 | ```ts 7 | const foo: string[] = []; 8 | ``` 9 | 10 | якщо потрібен масив масивів: 11 | 12 | ```ts 13 | [...new Array(6)]; 14 | ``` 15 | 16 | Якщо ви хочете створити масив, попередньо заповнений деяким вмістомб то використовуйте ES6 `Array.prototype.fill`: 17 | 18 | ```ts 19 | const foo: string[] = new Array(3).fill(''); 20 | console.log(foo); // ['','','']; 21 | ``` 22 | 23 | Якщо ви хочете створити масив попередньо визначеної довжини з викликами, ви можете скористатися оператором поширення: 24 | 25 | ```ts 26 | const someNumbers = [...new Array(3)].map((_,i) => i * 10); 27 | console.log(someNumbers); // [0,10,20]; 28 | ``` 29 | -------------------------------------------------------------------------------- /docs/tips/currying.md: -------------------------------------------------------------------------------- 1 | ## Currying 2 | Карирування 3 | 4 | Використовуйте ланцюжок функцій-стрілок: 5 | 6 | ```ts 7 | // функція каріровання 8 | let add = (x: number) => (y: number) => x + y; 9 | 10 | // легке використання 11 | add(123)(456); 12 | 13 | // часткове використання 14 | let add123 = add(123); 15 | 16 | // повне використання 17 | add123(456); 18 | ``` 19 | -------------------------------------------------------------------------------- /docs/tips/functionParameters.md: -------------------------------------------------------------------------------- 1 | # Function Parameters 2 | Параметри функції 3 | 4 | Якщо у вас є функція, яка приймає занадто багато параметрів або параметрів того самого типу, тоді ви можете змінити функцію, щоб замість цього приймати об’єкт. 5 | 6 | Розглянемо таку функцію: 7 | 8 | ```ts 9 | function foo(flagA: boolean, flagB: boolean) { 10 | // тіло функції 11 | } 12 | ``` 13 | 14 | З таким визначенням функції досить легко викликати її неправильно, наприклад. `foo(flagB, flagA)` та ви не отримаєте допомогу компілятора в цьому випадку. 15 | 16 | Краще змінити функцію, щоб вона отримувала обʼєкт: 17 | 18 | ```ts 19 | function foo(config: {flagA: boolean, flagB: boolean}) { 20 | const {flagA, flagB} = config; 21 | // тіло функції 22 | } 23 | ``` 24 | Зараз виклик функції став таким `foo({flagA, flagB})` що набогато краще для запобігання помилок та код-ревью. 25 | 26 | > Примітка: якщо ваша функція досить проста і ви не очікуєте великого відтоку, не соромтеся ігнорувати цю пораду 🌹. 27 | -------------------------------------------------------------------------------- /docs/tips/jquery.md: -------------------------------------------------------------------------------- 1 | ## JQuery Tips 2 | 3 | Увага: вам потрібно встановити `jquery.d.ts` файл для цього 4 | 5 | ### Quickly define a new plugin 6 | Швидка реєстрація. 7 | 8 | Створіть `jquery-foo.d.ts` з: 9 | 10 | ```ts 11 | interface JQuery { 12 | foo: any; 13 | } 14 | ``` 15 | 16 | тепер ви можете використовувати `$('something').foo({whateverYouWant:'hello jquery plugin'})` 17 | -------------------------------------------------------------------------------- /docs/tips/main.md: -------------------------------------------------------------------------------- 1 | # TIPs 2 | У цьому розділі ми представляємо ряд порад, які ми зібрали під час використання TypeScript у реальному світі. 3 | -------------------------------------------------------------------------------- /docs/tips/propertySetters.md: -------------------------------------------------------------------------------- 1 | ## Limit usage of property setters 2 | 3 | Віддавайте перевагу явним функціям set/get (наприклад, функціям `setBar` і `getBar`) над сеттерами/гетерами. 4 | 5 | Розглянемо наступний код: 6 | 7 | ```ts 8 | foo.bar = { 9 | a: 123, 10 | b: 456 11 | }; 12 | ``` 13 | 14 | За наявності сетера/гетера: 15 | 16 | ```ts 17 | class Foo { 18 | a: number; 19 | b: number; 20 | set bar(value:{a:number,b:number}) { 21 | this.a = value.a; 22 | this.b = value.b; 23 | } 24 | } 25 | let foo = new Foo(); 26 | ``` 27 | 28 | Це не є *добрим* використанням засобів налаштування властивостей. Людина, яка читає перший зразок коду, не має контексту щодо всіх речей, які зміняться. Тоді як хтось, хто викликає `foo.setBar(value)`, може мати ідею, що щось може змінитися на `foo`. 29 | 30 | > Бонусні бали: Пошук посилань працює краще, якщо у вас є інші функції. В інструментах TypeScript, якщо ви знайдете посилання на геттер або сеттер, ви отримаєте *обидва*, тоді як при явних викликах функцій ви отримаєте лише посилання на відповідну функцію. 31 | -------------------------------------------------------------------------------- /docs/tips/singleton.md: -------------------------------------------------------------------------------- 1 | # Singleton Pattern 2 | 3 | Традиційний шаблон singleton насправді використовується для подолання того факту, що весь код має бути в `класі`. 4 | 5 | ```ts 6 | class Singleton { 7 | private static instance: Singleton; 8 | private constructor() { 9 | // do something construct... 10 | } 11 | static getInstance() { 12 | if (!Singleton.instance) { 13 | Singleton.instance = new Singleton(); 14 | // ... any one time initialization goes here ... 15 | } 16 | return Singleton.instance; 17 | } 18 | someMethod() { } 19 | } 20 | 21 | let something = new Singleton() // Error: constructor of 'Singleton' is private. 22 | 23 | let instance = Singleton.getInstance() // do something with the instance... 24 | ``` 25 | 26 | Однак, якщо вам не потрібна відкладена ініціалізація, ви можете натомість просто використати `namespace`: 27 | ```ts 28 | namespace Singleton { 29 | // ... any one time initialization goes here ... 30 | export function someMethod() { } 31 | } 32 | // Usage 33 | Singleton.someMethod(); 34 | ``` 35 | 36 | > Попередження: Singleton — це лише дивовижна назва для [global](http://stackoverflow.com/a/142450/390330) 37 | 38 | Для більшості проектів `namespace` можна додатково замінити на *module*. 39 | 40 | ```ts 41 | // someFile.ts 42 | // ... any one time initialization goes here ... 43 | export function someMethod() { } 44 | 45 | // Usage 46 | import {someMethod} from "./someFile"; 47 | ``` 48 | 49 | 50 | -------------------------------------------------------------------------------- /docs/tips/statefulFunctions.md: -------------------------------------------------------------------------------- 1 | ## Stateful Functions 2 | Загальною особливістю в інших мовах програмування є використання ключового слова `static` для збільшення *lifetim* (а не *scope*) функціональної змінної, щоб вона жила поза викликами функції. Ось зразок `C`, який досягає цього: 3 | 4 | ```c 5 | void called() { 6 | static count = 0; 7 | count++; 8 | printf("Called : %d", count); 9 | } 10 | 11 | int main () { 12 | called(); // Called : 1 13 | called(); // Called : 2 14 | return 0; 15 | } 16 | ``` 17 | 18 | Оскільки JavaScript (або TypeScript) не має статичні функції, ви можете досягти того самого, використовуючи різні абстракції, які обертаються поверх локальної змінної, наприклад. використовуючи `class`: 19 | 20 | ```ts 21 | const {called} = new class { 22 | count = 0; 23 | called = () => { 24 | this.count++; 25 | console.log(`Called : ${this.count}`); 26 | } 27 | }; 28 | 29 | called(); // Called : 1 30 | called(); // Called : 2 31 | ``` 32 | 33 | > Розробники C++ також намагаються досягти цього за допомогою шаблону, який вони називають `functor`(клас, який замінює оператор `()`). 34 | -------------------------------------------------------------------------------- /docs/tips/staticConstructor.md: -------------------------------------------------------------------------------- 1 | # Static Constructors in TypeScript 2 | 3 | "Клас" TypeScript (як і "клас" JavaScript) не може мати статичного конструктора. Однак ви можете отримати той самий ефект досить легко, просто викликавши це самостійно: 4 | 5 | ```ts 6 | class MyClass { 7 | static initialize() { 8 | // Initialization 9 | } 10 | } 11 | MyClass.initialize(); 12 | ``` 13 | -------------------------------------------------------------------------------- /docs/tips/stringEnums.md: -------------------------------------------------------------------------------- 1 | ## String enums 2 | 3 | Іноді вам потрібна колекція рядків, зібраних під загальним ключем. До TypeScript 2.4 TypeScript підтримував лише числові переліки. Якщо ви використовуєте версії до 2.4, обхідним шляхом є використання [типів рядкового літералу для створення переліків на основі рядків шляхом поєднання з типами об’єднання](../types/literal-types.md). -------------------------------------------------------------------------------- /docs/tips/typeInstantiation.md: -------------------------------------------------------------------------------- 1 | ## Type Instantiation for Generics 2 | 3 | Скажімо, у вас є щось, що має загальний параметр, наприклад. клас `Foo`: 4 | 5 | ```ts 6 | class Foo{ 7 | foo: T; 8 | } 9 | ``` 10 | 11 | Ви хочете створити для нього спеціалізовану версію для певного типу. Шаблон полягає в тому, щоб скопіювати елемент у нову змінну та надати йому анотацію типу із заміною узагальнених типів на конкретні типи. наприклад якщо вам потрібен клас `Foo`: 12 | 13 | ```ts 14 | class Foo{ 15 | foo: T; 16 | } 17 | let FooNumber = Foo as { new ():Foo }; // ref 1 18 | ``` 19 | У `посиланні 1` ви говорите, що `FooNumber` — це те саме, що `Foo`, але розглядаєте його як щось, що при виклику оператора `new` дає екземпляр `Foo`. 20 | 21 | ### Inheritance 22 | Шаблон твердження Type є небезпечним, оскільки він довіряє вам, що ви робите правильні речі. Загальним шаблоном в інших мовах *для класів* є просто використання спадкування: 23 | 24 | ```ts 25 | class FooNumber extends Foo{} 26 | ``` 27 | 28 | Одне застереження: якщо ви використовуєте декоратори для базового класу, успадкований клас може не мати такої самої поведінки, як базовий клас (він більше не обгортається декоратором). 29 | 30 | Звичайно, якщо ви не спеціалізовали класи, вам все одно доведеться придумати шаблон примусу/твердження, який працює, тому ми спочатку показали загальний шаблон твердження, наприклад: 31 | 32 | ```ts 33 | function id(x: T) { return x; } 34 | const idNum = id as {(x:number):number}; 35 | ``` 36 | 37 | > Натхненний цим [питанням stackoverflow](http://stackoverflow.com/a/34864705/390330) 38 | -------------------------------------------------------------------------------- /docs/tips/typed-event.md: -------------------------------------------------------------------------------- 1 | ## Typesafe Event Emitter 2 | 3 | Традиційно в Node.js і традиційному JavaScript ви маєте єдиний джерело подій. Цей джерело подій внутрішньо відстежує слухача для різних типів подій 4 | 5 | ```ts 6 | const emitter = new EventEmitter(); 7 | // Emit: 8 | emitter.emit('foo', foo); 9 | emitter.emit('bar', bar); 10 | // Listen: 11 | emitter.on('foo', (foo)=>console.log(foo)); 12 | emitter.on('bar', (bar)=>console.log(bar)); 13 | ``` 14 | По суті, `EventEmitter` внутрішньо зберігає дані у формі відображених масивів: 15 | ```ts 16 | {foo: [fooListeners], bar: [barListeners]} 17 | ``` 18 | Замість цього, задля безпеки типу *event*, ви можете створити емітер *на* тип події: 19 | ```ts 20 | const onFoo = new TypedEvent(); 21 | const onBar = new TypedEvent(); 22 | 23 | // Emit: 24 | onFoo.emit(foo); 25 | onBar.emit(bar); 26 | // Listen: 27 | onFoo.on((foo)=>console.log(foo)); 28 | onBar.on((bar)=>console.log(bar)); 29 | ``` 30 | 31 | Це має такі переваги: 32 | * Типи подій легко знайти як змінні. 33 | * Змінні джерела подій легко переробляються незалежно. 34 | * Тип безпеки для структур даних подій. 35 | 36 | ### Reference TypedEvent 37 | ```ts 38 | export interface Listener { 39 | (event: T): any; 40 | } 41 | 42 | export interface Disposable { 43 | dispose(); 44 | } 45 | 46 | /** passes through events as they happen. You will not get events from before you start listening */ 47 | export class TypedEvent { 48 | private listeners: Listener[] = []; 49 | private listenersOncer: Listener[] = []; 50 | 51 | on = (listener: Listener): Disposable => { 52 | this.listeners.push(listener); 53 | return { 54 | dispose: () => this.off(listener) 55 | }; 56 | } 57 | 58 | once = (listener: Listener): void => { 59 | this.listenersOncer.push(listener); 60 | } 61 | 62 | off = (listener: Listener) => { 63 | var callbackIndex = this.listeners.indexOf(listener); 64 | if (callbackIndex > -1) this.listeners.splice(callbackIndex, 1); 65 | } 66 | 67 | emit = (event: T) => { 68 | /** Update any general listeners */ 69 | this.listeners.forEach((listener) => listener(event)); 70 | 71 | /** Clear the `once` queue */ 72 | if (this.listenersOncer.length > 0) { 73 | const toCall = this.listenersOncer; 74 | this.listenersOncer = []; 75 | toCall.forEach((listener) => listener(event)); 76 | } 77 | } 78 | 79 | pipe = (te: TypedEvent): Disposable => { 80 | return this.on((e) => te.emit(e)); 81 | } 82 | } 83 | ``` 84 | -------------------------------------------------------------------------------- /docs/tools/changelog.md: -------------------------------------------------------------------------------- 1 | ## Changelog 2 | > Читати файл розмітки з прогресом у проекті легше, ніж читати журнал фіксації. 3 | 4 | Автоматичне створення журналу змін із повідомлень комітів є досить поширеним шаблоном у наш час. Є проект під назвою [conventional-changelog](https://github.com/conventional-changelog/conventional-changelog) який генерує журнал змін із повідомлень про фіксацію, які відповідають *convention*. 5 | 6 | ### Commit message convention 7 | Найпоширенішою угодою є угода про повідомлення фіксації *angular*, яка [детально описана тут . Налаштування](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines). 8 | 9 | ### Setup 10 | 11 | * встановити: 12 | 13 | ```bash 14 | npm install standard-version -D 15 | ``` 16 | 17 | * Додайте ціль `script` до свого `package.json`: 18 | 19 | ```js 20 | { 21 | "scripts": { 22 | "release": "standard-version" 23 | } 24 | } 25 | ``` 26 | 27 | * Додатково: щоб автоматично надсилати новий *git commit and tag* плюс публікацію до npm, додайте `postrelease` сценарій: 28 | 29 | ```js 30 | { 31 | "scripts": { 32 | "release": "standard-version", 33 | "postrelease": "git push --follow-tags origin master && npm publish" 34 | } 35 | } 36 | ``` 37 | 38 | ### Releasing 39 | 40 | Простий запуск: 41 | 42 | ```bash 43 | npm run release 44 | ``` 45 | 46 | На основі повідомлень тип версії: `major` | `minor` | `patch` визначається автоматично. Щоб *explicitly* явно вказати версію, ви можете вказати `--release-as` наприклад:: 47 | 48 | ```bash 49 | npm run release -- --release-as minor 50 | ``` 51 | -------------------------------------------------------------------------------- /docs/tools/eslint.md: -------------------------------------------------------------------------------- 1 | # ESLint 2 | 3 | ESLint існував для лінтування JavaScript, але тепер він також стає дефакто лінтером для [TypeScript](https://github.com/Microsoft/TypeScript/issues/29288), завдяки 4 | [співпраці](https://eslint.org/blog/2019/01/future-typescript-eslint) між двома командами. 5 | 6 | ## Install 7 | Встановлення 8 | 9 | Щоб налаштувати ESLint для TypeScript, вам потрібні такі пакети: 10 | 11 | ```sh 12 | npm i eslint eslint-plugin-react @typescript-eslint/parser @typescript-eslint/eslint-plugin 13 | ``` 14 | 15 | > TIP: eslint називає свої пакети з правилами "plugin" 16 | 17 | * eslint : Core eslint 18 | * eslint-plugin-react : Правіла для react від eslint. [Supported rules list](https://github.com/yannickcr/eslint-plugin-react#list-of-supported-rules) 19 | * @typescript-eslint/parse : Дозволяє eslint розуміти ts / tsx files 20 | * @typescript-eslint/eslint-plugin : Для правил TypeScript. [Supported rules list](https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#supported-rules) 21 | 22 | > Как ви бачите, 2 eslint пакети (для використання js та ts) та 2 @typescript-eslint пакета (для ts). Така звишена увага для TypeScript не *that much*. 23 | 24 | ## Configure 25 | Конфігурація 26 | 27 | Створіть `.eslintrc.js`: 28 | 29 | ```js 30 | module.exports = { 31 | parser: '@typescript-eslint/parser', 32 | parserOptions: { 33 | project: './tsconfig.json', 34 | }, 35 | plugins: ['@typescript-eslint'], 36 | extends: [ 37 | 'plugin:react/recommended', 38 | 'plugin:@typescript-eslint/recommended', 39 | ], 40 | rules: { 41 | // Правила перезапису, указані в розширених конфігураціях, наприклад 42 | // "@typescript-eslint/explicit-function-return-type": "off", 43 | } 44 | ``` 45 | 46 | ## Run 47 | Використання 48 | 49 | У вашому `package.json` додайте до `scripts`: 50 | 51 | ```json 52 | { 53 | "scripts": { 54 | "lint": "eslint \"src/**\"" 55 | } 56 | } 57 | ``` 58 | 59 | Тепер ви можете `npm run lint` для перевірки. 60 | 61 | ## Configure VSCode 62 | Конфігурація VSCode 63 | 64 | * Встановіть розширення https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint 65 | 66 | * Додайте до `settings.json`: 67 | ```js 68 | "eslint.validate": [ 69 | "javascript", 70 | "javascriptreact", 71 | {"language": "typescript", "autoFix": true }, 72 | {"language": "typescriptreact", "autoFix": true } 73 | ], 74 | ``` 75 | -------------------------------------------------------------------------------- /docs/tools/husky.md: -------------------------------------------------------------------------------- 1 | # Husky 2 | 3 | > Husky може захистити вас від поганих комітів та відправок 🐶! 4 | 5 | Якщо ви хочете запустити деякий код JavaScript / TypeScript до того, як відбудеться коміт, інструментом для цього є Husky. 6 | 7 | Наприклад, ви можете використовувати Husky, щоб переконатися, що файли форматуються prettier автоматично, тож вам більше не доведеться турбуватися про форматування файлів вручну, а натомість зосередитися на меті коду. Ось налаштування: 8 | 9 | 10 | * `npm install husky -D` 11 | * Add `scripts` to `package.json`: 12 | 13 | ``` 14 | "precommit": "npm run prettier:write", 15 | ``` 16 | 17 | Тепер щоразу, коли ви фіксуєте код і потрібно внести будь-які зміни форматування, ви отримуватимете їх як *modified* файл у своєму журналі git. Ви можете спробувати зараз 18 | 19 | * Якщо ви вже просунули (push) свій код, просто зафіксуйте їх у коментарі `pretty`. 20 | * Якщо ви не просунули свій код, змініть свій останній комміт і виглядайте як супергерой. 21 | -------------------------------------------------------------------------------- /docs/tools/intro.md: -------------------------------------------------------------------------------- 1 | # Tools 2 | Інструменти 3 | 4 | Ось кілька чудових інструментів, які я рекомендую вам використовувати або принаймні спробувати у своїх проектах TypeScript. 5 | -------------------------------------------------------------------------------- /docs/tools/prettier.md: -------------------------------------------------------------------------------- 1 | # Prettier 2 | 3 | Prettier — це чудовий інструмент від Facebook, який робить форматування коду настільки простим, що варто згадати про нього. Налаштувати TypeScript за допомогою наших рекомендованих налаштувань проекту (також відомого як усе в папці `src`) надзвичайно просто: 4 | 5 | ## Setup 6 | Наставлення 7 | 8 | * `npm install prettier -D` 9 | * Add `scripts` to `package.json`: 10 | 11 | ``` 12 | "prettier:base": "prettier --parser typescript --single-quote", 13 | "prettier:check": "npm run prettier:base -- --list-different \"src/**/*.{ts,tsx}\"", 14 | "prettier:write": "npm run prettier:base -- --write \"src/**/*.{ts,tsx}\"" 15 | ``` 16 | 17 | ## Usage 18 | Використання 19 | 20 | На вашому сервері збірки: 21 | * `npm run prettier:check` 22 | 23 | Під час розробки (або перед комітом): 24 | * `npm run prettier:write` 25 | -------------------------------------------------------------------------------- /docs/types/@types.md: -------------------------------------------------------------------------------- 1 | # `@types` 2 | 3 | [Definitely Typed](https://github.com/DefinitelyTyped/DefinitelyTyped) безумовно, є однією з найбільших переваг TypeScript. Спільнота фактично пішла вперед і **documented** майже 90% найкращих проектів JavaScript. 4 | 5 | Це означає, що ви можете використовувати ці проекти в дуже інтерактивний та дослідницький спосіб, не потрібно відкривати документи в окремому вікні та стежити за тим, щоб ви не зробили помилки. 6 | 7 | ## Using `@types` 8 | 9 | Встановлення досить просте, оскільки воно працює поверх `npm`. Отже, як приклад, ви можете встановити визначення типу для`jquery` просто так: 10 | 11 | ``` 12 | npm install @types/jquery --save-dev 13 | ``` 14 | 15 | `@types` підтримує визначення типів *global* i *module*. 16 | 17 | 18 | ### Global `@types` 19 | 20 | За замовчуванням усі визначення, які підтримують глобальне споживання, включаються автоматично. наприклад для`jquery` ви повинні мати можливість просто почати використовувати `$` *globally* у своєму проекті. 21 | 22 | Однак для *libraries* (наприклад `jquery`) я зазвичай рекомендую використовувати *modules*: 23 | 24 | ### Module `@types` 25 | 26 | Після інсталяції не потрібна спеціальна конфігурація. Ви просто використовуєте його як модуль, наприклад: 27 | 28 | ```ts 29 | import * as $ from "jquery"; 30 | 31 | // Use $ at will in this module :) 32 | ``` 33 | 34 | ## Controlling Globals 35 | 36 | Як видно, наявність визначення, яке автоматично допускає глобальний витік, може бути проблемою для деяких команд. Тож ви можете вибрати *explicitly* лише введення типів, які мають сенс за допомогою `tsconfig.json` `compilerOptions.types` наприклад: 37 | 38 | ```json 39 | { 40 | "compilerOptions": { 41 | "types" : [ 42 | "jquery" 43 | ] 44 | } 45 | } 46 | ``` 47 | 48 | Вище показано зразок, де дозволено використовувати лише `jquery`. Навіть якщо особа встановить інше визначення, наприклад `npm install @types/node` його глобальні значення (наприклад,[`process`](https://nodejs.org/api/process.html))не просочуватимуться у ваш код, доки ви не додасте їх до опції типів `tsconfig.json`. 49 | -------------------------------------------------------------------------------- /docs/types/ambient/d.ts.md: -------------------------------------------------------------------------------- 1 | ### Declaration file 2 | Ви можете повідомити TypeScript, що ви намагаєтеся описати код, який існує в іншому місці (наприклад, написаний у JavaScript/CoffeeScript/середовищі виконання, як-от браузер або Node.js), використовуючи ключове слово `declare`. Як короткий приклад: 3 | 4 | ```ts 5 | foo = 123; // Error: `foo` is not defined 6 | ``` 7 | vs. 8 | ```ts 9 | declare var foo: any; 10 | foo = 123; // allowed 11 | ``` 12 | 13 | Ви можете розмістити ці оголошення у файлі `.ts` або у файлі `.d.ts`. Ми настійно рекомендуємо, щоб у ваших реальних проектах ви використовували окремий `.d.ts` (почніть з такого, який називається щось на зразок `global.d.ts` або `vendor.d.ts`). 14 | 15 | Якщо файл має розширення `.d.ts`, тоді кожне визначення кореневого рівня має мати префікс ключового слова `declare`. Це допомагає автору зрозуміти, що *no code emitted by TypeScript*. Автор повинен переконатися, що оголошений елемент існуватиме під час виконання. 16 | 17 | > * Оголошення навколишнього середовища - це обіцянка, яку ви робите з компілятором. Якщо вони не існують під час виконання, і ви спробуєте їх використати, все буде зламано без попередження. 18 | > 19 | * Оголошення середовища схожі на документи. Якщо джерело змінюється, документи потрібно постійно оновлювати. Отже, у вас може бути нова поведінка, яка працює під час виконання, але ніхто не оновив декларацію середовища, і, отже, ви отримуєте помилки компілятора. 20 | -------------------------------------------------------------------------------- /docs/types/ambient/intro.md: -------------------------------------------------------------------------------- 1 | ## Ambient Declarations 2 | 3 | Як ми згадували в [why TypeScript](../../why-typescript.md): 4 | 5 | > Головною метою розробки TypeScript було зробити можливим безпечне та просте використання існуючих бібліотек JavaScript у TypeScript. TypeScript робить це за допомогою *declaration*. 6 | 7 | Оголошення середовища дозволяють *безпечно використовувати наявні популярні бібліотеки JavaScript* і *поступово перенесіть свій проект JavaScript/CoffeeScript/Other-Compile-To-Js-Language на TypeScript*. 8 | 9 | Вивчення шаблонів у деклараціях середовища для *third party JavaScript code* також є гарною практикою для анотування *вашої* бази коду TypeScript. Ось чому ми представляємо його так рано. 10 | -------------------------------------------------------------------------------- /docs/types/ambient/variables.md: -------------------------------------------------------------------------------- 1 | ### Variables 2 | Наприклад, щоб повідомити TypeScript про [`process` variable](https://nodejs.org/api/process.html) you *можете* зробити: 3 | 4 | ```ts 5 | declare var process: any; 6 | ``` 7 | 8 | > Вам *потрібно* робити це для `process`, оскільки вже існує [community maintained `node.d.ts`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/node/index.d.ts). 9 | 10 | Це дозволяє вам використовувати змінну `process` без скарг TypeScript: 11 | 12 | ```ts 13 | process.exit(); 14 | ``` 15 | 16 | Ми рекомендуємо використовувати інтерфейс, де це можливо, наприклад: 17 | 18 | ```ts 19 | interface Process { 20 | exit(code?: number): void; 21 | } 22 | declare var process: Process; 23 | ``` 24 | 25 | Це дозволяє іншим людям *розширити* природу цих глобальних змінних, водночас повідомляючи TypeScript про такі зміни. наприклад Розглянемо наступний випадок, коли ми додаємо функцію `exitWithLogging` для обробки для нашої коду: 26 | 27 | ```ts 28 | interface Process { 29 | exitWithLogging(code?: number): void; 30 | } 31 | process.exitWithLogging = function() { 32 | console.log("exiting"); 33 | process.exit.apply(process, arguments); 34 | }; 35 | ``` 36 | 37 | Далі розглянемо інтерфейси трохи докладніше. 38 | -------------------------------------------------------------------------------- /footer.md: -------------------------------------------------------------------------------- 1 | [![fork me](/images/github.png) Fork me on github](https://github.com/basarat/typescript-book/) 2 | -------------------------------------------------------------------------------- /header.html: -------------------------------------------------------------------------------- 1 | 19 | -------------------------------------------------------------------------------- /images/atomts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtfulBits/typescript-book/b140230f7a46921e011db81728019ea00900183f/images/atomts.png -------------------------------------------------------------------------------- /images/designtsx-banner-large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtfulBits/typescript-book/b140230f7a46921e011db81728019ea00900183f/images/designtsx-banner-large.png -------------------------------------------------------------------------------- /images/designtsx-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtfulBits/typescript-book/b140230f7a46921e011db81728019ea00900183f/images/designtsx-banner.png -------------------------------------------------------------------------------- /images/errors/interpreting-errors/ide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtfulBits/typescript-book/b140230f7a46921e011db81728019ea00900183f/images/errors/interpreting-errors/ide.png -------------------------------------------------------------------------------- /images/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtfulBits/typescript-book/b140230f7a46921e011db81728019ea00900183f/images/github.png -------------------------------------------------------------------------------- /images/promise states and fates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtfulBits/typescript-book/b140230f7a46921e011db81728019ea00900183f/images/promise states and fates.png -------------------------------------------------------------------------------- /images/promise states and fates.vsd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtfulBits/typescript-book/b140230f7a46921e011db81728019ea00900183f/images/promise states and fates.vsd -------------------------------------------------------------------------------- /images/venn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtfulBits/typescript-book/b140230f7a46921e011db81728019ea00900183f/images/venn.png -------------------------------------------------------------------------------- /images/venn.vsd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtfulBits/typescript-book/b140230f7a46921e011db81728019ea00900183f/images/venn.vsd -------------------------------------------------------------------------------- /snippets/md-snippets.cson: -------------------------------------------------------------------------------- 1 | '.source.gfm': 2 | 'include': 3 | 'prefix': 'include' 4 | 'body': """ 5 | {% include "${1:./path}.md" %} 6 | """ --------------------------------------------------------------------------------