├── .gitattributes ├── .gitignore ├── CONTRIBUTING.md ├── GLOSSARY.md ├── IMLAKURALLARI.md ├── LICENSE.md ├── README.md ├── SUMMARY.md ├── book.json ├── code ├── 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 ├── errors │ ├── errors.js │ ├── 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 │ ├── 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-extensibility.md ├── classes-super.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 │ └── main.md ├── for...of.md ├── future-javascript.md ├── generators.md ├── getting-started.md ├── iterators.md ├── javascript │ ├── awful.md │ ├── closure.md │ └── recap.md ├── jsx │ └── tsx.md ├── let.md ├── options │ ├── intro.md │ ├── noImplicitAny.md │ └── strictNullChecks.md ├── project │ ├── compilation-context.md │ ├── declarationspaces.md │ ├── external-modules.md │ ├── files.md │ ├── globals.md │ ├── module-resolution.md │ ├── modules.md │ ├── namespaces.md │ ├── project.md │ └── tsconfig.md ├── promise.md ├── quick │ ├── browser.md │ └── nodejs.md ├── rest-parameters.md ├── spread-operator.md ├── staging │ ├── async-await.md │ └── generators.md ├── styleguide │ ├── sample.js │ ├── sample.ts │ ├── styleguide.md │ └── tsconfig.json ├── template-strings.md ├── tips │ ├── bind.md │ ├── build-toggles.md │ ├── classesAreUseful.md │ ├── currying.md │ ├── defaultIsBad.md │ ├── functionParameters.md │ ├── jquery.md │ ├── lazyObjectLiteralInitialization.md │ ├── main.md │ ├── mixins.md │ ├── nominalTyping.md │ ├── null.md │ ├── outFile.md │ ├── propertySetters.md │ ├── quickObjectReturn.md │ ├── singleton.md │ ├── statefulFunctions.md │ ├── staticConstructor.md │ ├── stringEnums.md │ ├── truthy.md │ └── typeInstantiation.md ├── types │ ├── @types.md │ ├── advanced.md │ ├── ambient │ │ ├── d.ts.md │ │ ├── intro.md │ │ └── variables.md │ ├── discriminated-unions.md │ ├── freshness.md │ ├── functions.md │ ├── generics.md │ ├── index-signatures.md │ ├── interfaces.md │ ├── lib.d.ts.md │ ├── literal-types.md │ ├── migrating.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 ├── images ├── atomts.png ├── github.png ├── promise states and fates.png ├── promise states and fates.vsd ├── venn.png └── venn.vsd └── snippets └── md-snippets.cson /.gitattributes: -------------------------------------------------------------------------------- 1 | # core.autocrlf 2 | * text=auto 3 | 4 | *.js linguist-language=TypeScript 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .alm 2 | *.DS_Store 3 | 4 | # Node rules: 5 | ## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 6 | .grunt 7 | 8 | ## Dependency directory 9 | ## Commenting this out is preferred by some people, see 10 | ## https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git 11 | node_modules 12 | 13 | # Book build output 14 | _book 15 | 16 | # eBook build output 17 | *.epub 18 | *.mobi 19 | *.pdf 20 | -------------------------------------------------------------------------------- /GLOSSARY.md: -------------------------------------------------------------------------------- 1 | # Özet bilgi 2 | ## Amaç 3 | Bu sözlük ile, kitaptaki anlam ve kelime bütünlüğünün sağlanması hedeflenmektedir. 4 | 5 | ## Kullanım 6 | Çeviri yapılırken karşılaşılan teknik terimlerin Türkçe çevirilerini yapmadan önce bu sayfaya göz atılması gerekmektedir. Aşağıdaki sözlük tablosunda, çevirisi yapılacak olan teknik terimin kabul edilmiş bir karşılığı varsa, bu karşılığın kullanılması gerekmektedir. 7 | 8 | Eğer sözlükte olmayan bir terim ile karşılaşılmışsa, istenilen çeviri, tabloya da girilerek gönderilir. 9 | 10 | Fakat bazı terimlerin Türkçe çevrimi, cümleyi anlamsız bir hale getirebilmektedir. Bunun için "terim açıklamaları" bölümü kullanılıp, buraya bağlantı verilebilir. 11 | 12 | 13 | # Sözlük 14 | | İngilizce | Türkçe | 15 | | ------------------------------------- |---------------------------------------| 16 | | Hello world! | Merhaba dünya! | 17 | | Issue | Görev | 18 | | Contributor | Katkıda bulunan kişi | 19 | | Object | Nesne | 20 | | Event | Olay | 21 | | String | Karakter dizimi | 22 | | Escape character (`\`) | Kaçış karakteri | 23 | | Inheritance | Kalıtım | 24 | | Callback | Geri çağırım | 25 | | Optional | İsteğe bağlı | 26 | | Type | Tip | 27 | | Engine | Motor | 28 | | Namespace | Aduzayı | 29 | # Terim açıklamaları 30 | * Duck Typing: Eğer bir ördek gibi yürüyor ve bir ördek gibi "vak"lıyorsa, o zaman bu bir ördektir. Bir nesne yapısal olarak tüm üyelere sahipse, diğer şeylerin de (ne olduğu önemli değil) var olduğu kabul edilir. 31 | -------------------------------------------------------------------------------- /IMLAKURALLARI.md: -------------------------------------------------------------------------------- 1 | # Kısaca, Türkçe dil kuralları üzerine 2 | ## Noktalama işaretleri 3 | * Nokta, virgül, soru işareti, ünlem, noktalı virgül, iki nokta üst üste gibi noktalama işaretlerinden sonra boşluk bırakılır. Öncesinde bir boşluk olmamalıdır. 4 | * Parantez içinde yazılacak ifade, parantez işaretlerine bitişiktir. İlk parantezden önce boşluk ve sonra parantezden sonra bir boşluk bırakılmalıdır. Örn: Typescript çok güzel (bana göre) bir dildir. 5 | * Nokta, iki nokta üst üste, soru işareti ve ünlem işaretinden sonraki kelimelerin baş harfi büyük olmalıdır. 6 | 7 | ## "Ayrı mı yazmalıyım bitişik mi?" 8 | * Hiçbir şey 9 | * Birkaç 10 | * Bir şey 11 | * Bir kez 12 | 13 | ## Çeviri 14 | http://tureng.com/ 15 | https://translate.google.com/ 16 | Deyimler ve teknik terimlerin çevirimi noktasında yardımcı olabilir. -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Creative Commons 2 | 3 | https://creativecommons.org/licenses/by/4.0/ 4 | -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | { 2 | "gitbook": ">=3.2.1", 3 | "plugins": ["edit-link", "github"], 4 | "pluginsConfig": { 5 | "edit-link": { 6 | "base": "https://github.com/basarat/typescript-book/tree/master", 7 | "label": "Edit This Page" 8 | }, 9 | "github": { 10 | "url": "https://github.com/basarat/typescript-book/" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /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/errors/errors.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | ga(); 3 | -------------------------------------------------------------------------------- /code/errors/errors.ts: -------------------------------------------------------------------------------- 1 | ga(); 2 | 3 | import {debounce} from "underscore"; 4 | -------------------------------------------------------------------------------- /code/errors/tsconfig.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /code/es6/classes/abstract.js: -------------------------------------------------------------------------------- 1 | exports.foo = 123; 2 | var Restable = (function () { 3 | function Restable() { 4 | this.abstract = toJSON(); 5 | } 6 | return Restable; 7 | })(); 8 | -------------------------------------------------------------------------------- /code/es6/classes/abstract.ts: -------------------------------------------------------------------------------- 1 | export var foo = 123; 2 | 3 | class Restable { 4 | abstract toJSON() : any; 5 | } 6 | 7 | -------------------------------------------------------------------------------- /code/es6/classes/class.js: -------------------------------------------------------------------------------- 1 | var __extends = this.__extends || function (d, b) { 2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 3 | function __() { this.constructor = d; } 4 | __.prototype = b.prototype; 5 | d.prototype = new __(); 6 | }; 7 | var Point = (function () { 8 | function Point(x, y) { 9 | this.x = x; 10 | this.y = y; 11 | } 12 | Point.prototype.add = function (point) { 13 | return new Point(this.x + point.x, this.y + point.y); 14 | }; 15 | return Point; 16 | })(); 17 | var p1 = new Point(0, 10); 18 | var p2 = new Point(10, 20); 19 | var p3 = p1.add(p2); 20 | var Point3D = (function (_super) { 21 | __extends(Point3D, _super); 22 | function Point3D(x, y, z) { 23 | _super.call(this, x, y); 24 | this.z = z; 25 | } 26 | Point3D.prototype.add = function (point) { 27 | var point2D = _super.prototype.add.call(this, point); 28 | return new Point3D(point2D.x, point2D.y, this.z + point.z); 29 | }; 30 | return Point3D; 31 | })(Point); 32 | var Something = (function () { 33 | function Something() { 34 | Something.instances++; 35 | } 36 | Something.instances = 0; 37 | return Something; 38 | })(); 39 | var s1 = new Something(); 40 | var s2 = new Something(); 41 | console.log(Something.instances); 42 | -------------------------------------------------------------------------------- /code/es6/classes/class.ts: -------------------------------------------------------------------------------- 1 | class Point { 2 | x: number; 3 | y: number; 4 | constructor(x: number, y: number) { 5 | this.x = x; 6 | this.y = y; 7 | } 8 | add(point: Point) { 9 | return new Point(this.x + point.x, this.y + point.y); 10 | } 11 | } 12 | 13 | var p1 = new Point(0, 10); 14 | var p2 = new Point(10, 20); 15 | var p3 = p1.add(p2); // {x:10,y:30} 16 | 17 | class Point3D extends Point { 18 | z: number; 19 | constructor(x: number, y: number, z: number) { 20 | super(x, y); 21 | this.z = z; 22 | } 23 | add(point: Point3D) { 24 | var point2D = super.add(point); 25 | return new Point3D(point2D.x, point2D.y, this.z + point.z); 26 | } 27 | } 28 | 29 | class Something { 30 | static instances = 0; 31 | constructor() { 32 | Something.instances++; 33 | } 34 | } 35 | 36 | var s1 = new Something(); 37 | var s2 = new Something(); 38 | console.log(Something.instances); // 2 39 | -------------------------------------------------------------------------------- /code/es6/classes/super.js: -------------------------------------------------------------------------------- 1 | var __extends = (this && this.__extends) || function (d, b) { 2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 3 | function __() { this.constructor = d; } 4 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 5 | }; 6 | exports.foo = 123; 7 | var asdf; 8 | (function (asdf) { 9 | var Base = (function () { 10 | function Base() { 11 | } 12 | Base.prototype.log = function () { console.log('hello world'); }; 13 | return Base; 14 | })(); 15 | var Child = (function (_super) { 16 | __extends(Child, _super); 17 | function Child() { 18 | _super.apply(this, arguments); 19 | } 20 | Child.prototype.logWorld = function () { _super.prototype.log.call(this); }; 21 | ; 22 | return Child; 23 | })(Base); 24 | })(asdf || (asdf = {})); 25 | var bse; 26 | (function (bse) { 27 | var Base = (function () { 28 | function Base() { 29 | this.log = function () { console.log('hello world'); }; 30 | } 31 | return Base; 32 | })(); 33 | var Child = (function (_super) { 34 | __extends(Child, _super); 35 | function Child() { 36 | _super.apply(this, arguments); 37 | } 38 | Child.prototype.logWorld = function () { this.log(); }; 39 | ; 40 | return Child; 41 | })(Base); 42 | })(bse || (bse = {})); 43 | var quz; 44 | (function (quz) { 45 | var Base = (function () { 46 | function Base() { 47 | this.log = function () { console.log('hello world'); }; 48 | } 49 | return Base; 50 | })(); 51 | var Child = (function (_super) { 52 | __extends(Child, _super); 53 | function Child() { 54 | _super.apply(this, arguments); 55 | } 56 | Child.prototype.logWorld = function () { _super.prototype.log.call(this); }; 57 | ; 58 | return Child; 59 | })(Base); 60 | })(quz || (quz = {})); 61 | -------------------------------------------------------------------------------- /code/es6/classes/super.ts: -------------------------------------------------------------------------------- 1 | export var foo = 123; 2 | 3 | module asdf { 4 | class Base { 5 | log() { console.log('hello world'); } 6 | } 7 | 8 | class Child extends Base { 9 | logWorld() { super.log() }; 10 | } 11 | } 12 | 13 | module bse { 14 | class Base { 15 | log = () => { console.log('hello world'); } 16 | } 17 | 18 | class Child extends Base { 19 | logWorld() { this.log() }; 20 | } 21 | } 22 | 23 | module quz { 24 | class Base { 25 | log = () => { console.log('hello world'); } 26 | } 27 | 28 | class Child extends Base { 29 | logWorld() { super.log() }; // ERROR : only `public` and `protected` methods of base class are accessible via `super` 30 | } 31 | } -------------------------------------------------------------------------------- /code/es6/classes/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.4.1", 3 | "compilerOptions": { 4 | "target": "es5", 5 | "module": "commonjs", 6 | "declaration": false, 7 | "noImplicitAny": false, 8 | "removeComments": true, 9 | "noLib": false 10 | }, 11 | "filesGlob": [ 12 | "./**/*.ts", 13 | "!./node_modules/**/*.ts" 14 | ], 15 | "files": [ 16 | "./abstract.ts", 17 | "./class.ts", 18 | "./super.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /code/es6/const.js: -------------------------------------------------------------------------------- 1 | exports.asdfasdfasfadf = 123; 2 | var mustbeinit; 3 | (function (mustbeinit) { 4 | var foo; 5 | })(mustbeinit || (mustbeinit = {})); 6 | var cantbechanged; 7 | (function (cantbechanged) { 8 | var foo = 123; 9 | foo = 456; 10 | })(cantbechanged || (cantbechanged = {})); 11 | var block; 12 | (function (block) { 13 | var foo = 123; 14 | if (true) { 15 | var foo_1 = 456; 16 | } 17 | })(block || (block = {})); 18 | var protectvariablereference; 19 | (function (protectvariablereference) { 20 | var foo = { bar: 123 }; 21 | foo = { bar: 456 }; 22 | })(protectvariablereference || (protectvariablereference = {})); 23 | var noProtectDeep; 24 | (function (noProtectDeep) { 25 | var foo = { bar: 123 }; 26 | foo.bar = 456; 27 | })(noProtectDeep || (noProtectDeep = {})); 28 | -------------------------------------------------------------------------------- /code/es6/const.ts: -------------------------------------------------------------------------------- 1 | export var asdfasdfasfadf = 123; 2 | 3 | 4 | namespace mustbeinit { 5 | const foo; 6 | } 7 | 8 | namespace cantbechanged { 9 | const foo = 123; 10 | foo = 456; 11 | } 12 | 13 | 14 | namespace block { 15 | const foo = 123; 16 | if (true) { 17 | const foo = 456; // Allowed as its a new variable limited to this `if` block 18 | } 19 | } 20 | 21 | 22 | namespace protectvariablereference { 23 | const foo = { bar: 123 }; 24 | foo = { bar: 456 }; // ERROR : Left hand side of an assignment expression cannot be a constant 25 | } 26 | 27 | 28 | namespace noProtectDeep { 29 | const foo = { bar: 123 }; 30 | foo.bar = 456; // Allowed! 31 | } 32 | -------------------------------------------------------------------------------- /code/es6/destructuring.js: -------------------------------------------------------------------------------- 1 | exports.destructuring = true; 2 | var m1; 3 | (function (m1) { 4 | var x = 1, y = 2; 5 | _a = [ 6 | y, 7 | x 8 | ], x = _a[0], y = _a[1]; 9 | console.log(x, y); 10 | var _a; 11 | })(m1 || (m1 = {})); 12 | var m2; 13 | (function (m2) { 14 | var rect = { 15 | x: 0, 16 | y: 10, 17 | width: 15, 18 | height: 20 19 | }; 20 | var x = rect.x, y = rect.y, width = rect.width, height = rect.height; 21 | console.log(x, y, width, height); 22 | })(m2 || (m2 = {})); 23 | var m3; 24 | (function (m3) { 25 | var _a = [ 26 | 1, 27 | 2, 28 | 3, 29 | 4 30 | ], x = _a[0], y = _a[1], remaining = _a.slice(2); 31 | console.log(x, y, remaining); 32 | })(m3 || (m3 = {})); 33 | var m3; 34 | (function (m3) { 35 | var _a = [ 36 | 1, 37 | 2, 38 | 3, 39 | 4 40 | ], x = _a[0], remaining = _a.slice(2); 41 | console.log(x, remaining); 42 | })(m3 || (m3 = {})); 43 | -------------------------------------------------------------------------------- /code/es6/destructuring.ts: -------------------------------------------------------------------------------- 1 | export var destructuring = true; 2 | 3 | 4 | module m1 { 5 | var x = 1, y = 2; 6 | [x, y] = [y, x]; 7 | console.log(x, y); // 1,2 8 | } 9 | 10 | module m2 { 11 | var rect = { x: 0, y: 10, width: 15, height: 20 }; 12 | var {x, y, width, height} = rect; 13 | console.log(x, y, width, height); // 0,10,15,20 14 | } 15 | 16 | module m3 { 17 | var [x, y, ...remaining] = [1, 2, 3, 4]; 18 | console.log(x, y, remaining); // 1, 2, [3,4] 19 | } 20 | 21 | module m3 { 22 | var [x, , ...remaining] = [1, 2, 3, 4]; 23 | console.log(x, remaining); // 1, [3,4] 24 | } 25 | -------------------------------------------------------------------------------- /code/es6/enums.ts: -------------------------------------------------------------------------------- 1 | export var foo = 123; 2 | 3 | enum Color { 4 | Red, 5 | Green, 6 | Blue 7 | } 8 | 9 | enum Color { 10 | DarkRed = 3, 11 | DarkGreen, 12 | DarkBlue 13 | } 14 | 15 | var col = Color.Red; 16 | col = 0; // Effectively same as Color.Red 17 | 18 | 19 | enum Tristate { 20 | False, 21 | True, 22 | Unknown 23 | } 24 | 25 | var lie = Tristate.False; 26 | 27 | /*enum AnimalFlags { 28 | None = 0, 29 | HasClaws = 1 << 0, 30 | CanFly = 1 << 1, 31 | EatsFish = 1 << 2, 32 | Endangered = 1 << 3 33 | }*/ 34 | 35 | enum AnimalFlags { 36 | None = 0, 37 | HasClaws = 1 << 0, 38 | CanFly = 1 << 1, 39 | } 40 | 41 | function printAnimalAbilities(animal) { 42 | var animalFlags = animal.flags; 43 | if (animalFlags & AnimalFlags.HasClaws) { 44 | console.log('animal has claws'); 45 | } 46 | if (animalFlags & AnimalFlags.CanFly) { 47 | console.log('animal can fly'); 48 | } 49 | if (animalFlags == AnimalFlags.None){ 50 | console.log('nothing'); 51 | } 52 | } 53 | 54 | var animal = { flags: AnimalFlags.None }; 55 | printAnimalAbilities(animal); // nothing 56 | animal.flags |= AnimalFlags.HasClaws; 57 | printAnimalAbilities(animal); // animal has claws 58 | animal.flags &= ~AnimalFlags.HasClaws; 59 | printAnimalAbilities(animal); // nothing 60 | animal.flags |= AnimalFlags.HasClaws | AnimalFlags.CanFly; 61 | printAnimalAbilities(animal); // animal has claws, animal can fly 62 | 63 | 64 | namespace EnumsWithStatics { 65 | enum Weekday { 66 | Monday, 67 | Tuesday, 68 | Wednesday, 69 | Thursday, 70 | Friday, 71 | Saturday, 72 | Sunday 73 | } 74 | namespace Weekday { 75 | export function isBusinessDay(day: Weekday) { 76 | switch (day) { 77 | case Weekday.Saturday: 78 | case Weekday.Sunday: 79 | return false; 80 | default: 81 | return true; 82 | } 83 | } 84 | } 85 | 86 | const mon = Weekday.Monday; 87 | const sun = Weekday.Sunday; 88 | console.log(Weekday.isBusinessDay(mon)); // true 89 | console.log(Weekday.isBusinessDay(sun)); // false 90 | } 91 | -------------------------------------------------------------------------------- /code/es6/for..of.js: -------------------------------------------------------------------------------- 1 | exports.forof = true; 2 | var m0; 3 | (function (m0) { 4 | var someArray = [ 5 | 9, 6 | 2, 7 | 5 8 | ]; 9 | for (var item in someArray) { 10 | console.log(item); 11 | } 12 | })(m0 || (m0 = {})); 13 | var m1; 14 | (function (m1) { 15 | var someArray = [ 16 | 9, 17 | 2, 18 | 5 19 | ]; 20 | for (var _i = 0; _i < someArray.length; _i++) { 21 | var item = someArray[_i]; 22 | console.log(item); 23 | } 24 | })(m1 || (m1 = {})); 25 | var m2; 26 | (function (m2) { 27 | var hello = "is it me you're looking for?"; 28 | for (var _i = 0; _i < hello.length; _i++) { 29 | var char = hello[_i]; 30 | console.log(char); 31 | } 32 | })(m2 || (m2 = {})); 33 | var m2; 34 | (function (m2) { 35 | var articleParagraphs = document.querySelectorAll("article > p"); 36 | for (var _i = 0; _i < articleParagraphs.length; _i++) { 37 | var paragraph = articleParagraphs[_i]; 38 | paragraph.classList.add("read"); 39 | } 40 | })(m2 || (m2 = {})); 41 | -------------------------------------------------------------------------------- /code/es6/for..of.ts: -------------------------------------------------------------------------------- 1 | export var forof = true; 2 | 3 | module m0 { 4 | var someArray = [9, 2, 5]; 5 | for (var item in someArray) { 6 | console.log(item); 7 | } 8 | } 9 | 10 | module m1 { 11 | var someArray = [9, 2, 5]; 12 | for (var item of someArray) { 13 | console.log(item); 14 | } 15 | } 16 | 17 | module m2 { 18 | var hello = "is it me you're looking for?"; 19 | for (var char of hello) { 20 | console.log(char); // is it me you're looking for? 21 | } 22 | } 23 | 24 | module m2 { 25 | let articleParagraphs = document.querySelectorAll("article > p"); 26 | // Error: Nodelist is not an array type or a string type 27 | for (let paragraph of articleParagraphs) { 28 | paragraph.classList.add("read"); 29 | } 30 | } -------------------------------------------------------------------------------- /code/es6/forof.js: -------------------------------------------------------------------------------- 1 | exports.forof = true; 2 | var m0; 3 | (function (m0) { 4 | var someArray = [ 5 | 9, 6 | 2, 7 | 5 8 | ]; 9 | for (var item in someArray) { 10 | console.log(item); 11 | } 12 | })(m0 || (m0 = {})); 13 | var m1; 14 | (function (m1) { 15 | var someArray = [ 16 | 9, 17 | 2, 18 | 5 19 | ]; 20 | for (var _i = 0; _i < someArray.length; _i++) { 21 | var item = someArray[_i]; 22 | console.log(item); 23 | } 24 | })(m1 || (m1 = {})); 25 | var m2; 26 | (function (m2) { 27 | var hello = "is it me you're looking for?"; 28 | for (var _i = 0; _i < hello.length; _i++) { 29 | var char = hello[_i]; 30 | console.log(char); 31 | } 32 | })(m2 || (m2 = {})); 33 | var m2; 34 | (function (m2) { 35 | var articleParagraphs = document.querySelectorAll("article > p"); 36 | for (var _i = 0; _i < articleParagraphs.length; _i++) { 37 | var paragraph = articleParagraphs[_i]; 38 | paragraph.classList.add("read"); 39 | } 40 | })(m2 || (m2 = {})); 41 | -------------------------------------------------------------------------------- /code/es6/iterators.js: -------------------------------------------------------------------------------- 1 | var Component = (function () { 2 | function Component(name) { 3 | this.name = name; 4 | } 5 | return Component; 6 | }()); 7 | var Frame = (function () { 8 | function Frame(name, components) { 9 | this.name = name; 10 | this.components = components; 11 | this.pointer = 0; 12 | } 13 | Frame.prototype.next = function () { 14 | if (this.pointer < this.components.length) { 15 | return { 16 | done: false, 17 | value: this.components[this.pointer++] 18 | }; 19 | } 20 | else 21 | return { 22 | done: true 23 | }; 24 | }; 25 | return Frame; 26 | }()); 27 | var frame = new Frame("Door", [new Component("top"), new Component("bottom"), new Component("left"), new Component("right")]); 28 | var iteratorResult1 = frame.next(); 29 | var iteratorResult2 = frame.next(); 30 | var iteratorResult3 = frame.next(); 31 | var iteratorResult4 = frame.next(); 32 | var iteratorResult5 = frame.next(); 33 | var component = iteratorResult1.value; 34 | -------------------------------------------------------------------------------- /code/es6/iterators.ts: -------------------------------------------------------------------------------- 1 | // The book's chapter describes usage of Iterators with ES6 target 2 | // This example showing usage of iterators with ES5 target 3 | // 4 | // The example from the chapter should work in moderen browsers and Node 5 | // with target ES5 if you add es6.d.ts to the project 6 | 7 | class Component { 8 | constructor (public name: string) {} 9 | } 10 | 11 | class Frame { 12 | 13 | private pointer = 0; 14 | 15 | constructor(public name: string, public components: Component[]) {} 16 | 17 | public next(): {done: boolean, value?: Component} { 18 | if (this.pointer < this.components.length) { 19 | return { 20 | done: false, 21 | value: this.components[this.pointer++] 22 | } 23 | } else return { 24 | done: true 25 | } 26 | } 27 | 28 | } 29 | 30 | let frame = new Frame("Door", [new Component("top"), new Component("bottom"), new Component("left"), new Component("right")]); 31 | let iteratorResult1 = frame.next(); //{ done: false, value: Component { name: 'top' } } 32 | let iteratorResult2 = frame.next(); //{ done: false, value: Component { name: 'bottom' } } 33 | let iteratorResult3 = frame.next(); //{ done: false, value: Component { name: 'left' } } 34 | let iteratorResult4 = frame.next(); //{ done: false, value: Component { name: 'right' } } 35 | let iteratorResult5 = frame.next(); //{ done: true } 36 | 37 | //It is possible to access the value of iterator result via the value property: 38 | let component = iteratorResult1.value; //Component { name: 'top' } 39 | -------------------------------------------------------------------------------- /code/es6/let.js: -------------------------------------------------------------------------------- 1 | exports.asdfasdfasfadf = 123; 2 | var first; 3 | (function (first) { 4 | var something = [ 5 | 1, 6 | 2, 7 | 3 8 | ]; 9 | })(first || (first = {})); 10 | var second; 11 | (function (second) { 12 | var foo = 123; 13 | if (true) { 14 | var foo = 456; 15 | } 16 | console.log(foo); 17 | })(second || (second = {})); 18 | var third; 19 | (function (third) { 20 | var foo = 123; 21 | function test() { 22 | var foo = 456; 23 | } 24 | test(); 25 | console.log(foo); 26 | })(third || (third = {})); 27 | var fourth; 28 | (function (fourth) { 29 | var index = 0; 30 | var array = [ 31 | 1, 32 | 2, 33 | 3 34 | ]; 35 | for (var _index = 0; _index < array.length; _index++) { 36 | console.log(array[_index]); 37 | } 38 | console.log(index); 39 | })(fourth || (fourth = {})); 40 | var fifth; 41 | (function (fifth) { 42 | if (true) { 43 | var foo = 123; 44 | } 45 | })(fifth || (fifth = {})); 46 | var fifth; 47 | (function (fifth) { 48 | var foo = '123'; 49 | if (true) { 50 | var _foo = 123; 51 | } 52 | })(fifth || (fifth = {})); 53 | var closures; 54 | (function (closures) { 55 | var funcs = []; 56 | for (var i = 0; i < 3; i++) { 57 | funcs.push(function () { 58 | console.log(i); 59 | }); 60 | } 61 | for (var j = 0; j < 3; j++) { 62 | funcs[j](); 63 | } 64 | })(closures || (closures = {})); 65 | var closures2; 66 | (function (closures2) { 67 | var funcs = []; 68 | for (var i = 0; i < 3; i++) { 69 | (function () { 70 | var local = i; 71 | funcs.push(function () { 72 | console.log(local); 73 | }); 74 | })(); 75 | } 76 | for (var j = 0; j < 3; j++) { 77 | funcs[j](); 78 | } 79 | })(closures2 || (closures2 = {})); 80 | var closures3; 81 | (function (closures3) { 82 | var funcs = []; 83 | for (var i = 0; i < 3; i++) { 84 | funcs.push(function () { 85 | console.log(i); 86 | }); 87 | } 88 | for (var j = 0; j < 3; j++) { 89 | funcs[j](); 90 | } 91 | })(closures3 || (closures3 = {})); 92 | -------------------------------------------------------------------------------- /code/es6/let.ts: -------------------------------------------------------------------------------- 1 | export var asdfasdfasfadf = 123; 2 | 3 | module first { 4 | let something = [1, 2, 3]; 5 | 6 | 7 | } 8 | 9 | module second { 10 | var foo = 123; 11 | if (true) { 12 | var foo = 456; 13 | } 14 | console.log(foo); // 456 15 | } 16 | 17 | module third { 18 | var foo = 123; 19 | function test() { 20 | var foo = 456; 21 | } 22 | test(); 23 | console.log(foo); // 123 24 | } 25 | 26 | module fourth { 27 | var index = 0; 28 | var array = [1, 2, 3]; 29 | for (let index = 0; index < array.length; index++) { 30 | console.log(array[index]); 31 | } 32 | console.log(index); // 0 33 | } 34 | 35 | module fifth { 36 | if (true) { 37 | let foo = 123; 38 | } 39 | } 40 | 41 | module fifth { 42 | var foo = '123'; 43 | if (true) { 44 | let foo = 123; 45 | } 46 | } 47 | 48 | module closures { 49 | var funcs = []; 50 | // create a bunch of functions 51 | for (var i = 0; i < 3; i++) { 52 | funcs.push(function() { 53 | console.log(i); 54 | }) 55 | } 56 | // call them 57 | for (var j = 0; j < 3; j++) { 58 | funcs[j](); 59 | } 60 | } 61 | 62 | module closures2 { 63 | var funcs = []; 64 | // create a bunch of functions 65 | for (var i = 0; i < 3; i++) { 66 | (function() { 67 | var local = i; 68 | funcs.push(function() { 69 | console.log(local); 70 | }) 71 | })(); 72 | } 73 | // call them 74 | for (var j = 0; j < 3; j++) { 75 | funcs[j](); 76 | } 77 | } 78 | 79 | module closures3 { 80 | var funcs = []; 81 | // create a bunch of functions 82 | for (let i = 0; i < 3; i++) { // Error : loop contains 83 | funcs.push(function() { 84 | console.log(i); 85 | }) 86 | } 87 | // call them 88 | for (var j = 0; j < 3; j++) { 89 | funcs[j](); 90 | } 91 | } -------------------------------------------------------------------------------- /code/es6/rest-parameters.js: -------------------------------------------------------------------------------- 1 | var rest; 2 | (function (rest) { 3 | function iTakeItAll(first, second) { 4 | var allOthers = []; 5 | for (var _i = 2; _i < arguments.length; _i++) { 6 | allOthers[_i - 2] = arguments[_i]; 7 | } 8 | console.log(allOthers); 9 | } 10 | iTakeItAll('foo', 'bar'); 11 | iTakeItAll('foo', 'bar', 'bas', 'qux'); 12 | })(rest = exports.rest || (exports.rest = {})); 13 | -------------------------------------------------------------------------------- /code/es6/rest-parameters.ts: -------------------------------------------------------------------------------- 1 | export module rest { 2 | function iTakeItAll(first, second, ...allOthers) { 3 | console.log(allOthers); 4 | } 5 | iTakeItAll('foo', 'bar'); // [] 6 | iTakeItAll('foo', 'bar', 'bas', 'qux'); // ['bas','qux'] 7 | } -------------------------------------------------------------------------------- /code/es6/spread-operator.js: -------------------------------------------------------------------------------- 1 | var spread; 2 | (function (spread) { 3 | var list = [ 4 | 1, 5 | 2 6 | ]; 7 | list = list.concat([3, 4]); 8 | })(spread = exports.spread || (exports.spread = {})); 9 | -------------------------------------------------------------------------------- /code/es6/spread-operator.ts: -------------------------------------------------------------------------------- 1 | export module spread { 2 | var list = [1, 2]; 3 | list = [...list, 3, 4]; 4 | } -------------------------------------------------------------------------------- /code/es6/template-strings.js: -------------------------------------------------------------------------------- 1 | exports.templateStrings = '123'; 2 | var m1; 3 | (function (m1) { 4 | var lyrics = "Never gonna give you up \ 5 | \nNever gonna let you down"; 6 | console.log(lyrics); 7 | })(m1 || (m1 = {})); 8 | var m2; 9 | (function (m2) { 10 | var lyrics = "Never gonna give you up\nNever gonna let you down"; 11 | console.log(lyrics); 12 | })(m2 || (m2 = {})); 13 | var m3; 14 | (function (m3) { 15 | var lyrics = 'Never gonna give you up'; 16 | var html = '
' + lyrics + '
'; 17 | })(m3 || (m3 = {})); 18 | var m4; 19 | (function (m4) { 20 | var lyrics = 'Never gonna give you up'; 21 | var html = "
" + lyrics + "
"; 22 | })(m4 || (m4 = {})); 23 | var m5; 24 | (function (m5) { 25 | console.log("1 and 1 one make " + (1 + 1)); 26 | })(m5 || (m5 = {})); 27 | var m6; 28 | (function (m6) { 29 | var say = "a bird in hand > two in the bush"; 30 | var html = (_a = ["
I would just like to say : ", "
"], _a.raw = ["
I would just like to say : ", "
"], htmlEscape(_a, say)); 31 | function htmlEscape(literals) { 32 | var placeholders = []; 33 | for (var _i = 1; _i < arguments.length; _i++) { 34 | placeholders[_i - 1] = arguments[_i]; 35 | } 36 | var result = ""; 37 | for (var i = 0; i < placeholders.length; i++) { 38 | result += literals[i]; 39 | result += placeholders[i].replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(//g, '>'); 40 | } 41 | result += literals[literals.length - 1]; 42 | return result; 43 | } 44 | console.log(html); 45 | var _a; 46 | })(m6 || (m6 = {})); 47 | -------------------------------------------------------------------------------- /code/es6/template-strings.ts: -------------------------------------------------------------------------------- 1 | export var templateStrings = '123'; 2 | 3 | module m1 { 4 | var lyrics = "Never gonna give you up \ 5 | \nNever gonna let you down"; 6 | console.log(lyrics); 7 | } 8 | 9 | module m2 { 10 | var lyrics = `Never gonna give you up 11 | Never gonna let you down`; 12 | console.log(lyrics); 13 | } 14 | 15 | module m3 { 16 | var lyrics = 'Never gonna give you up'; 17 | var html = '
' + lyrics + '
'; 18 | } 19 | 20 | module m4 { 21 | var lyrics = 'Never gonna give you up'; 22 | var html = `
${lyrics}
`; 23 | } 24 | 25 | module m5 { 26 | console.log(`1 and 1 one make ${1 + 1}`); 27 | } 28 | 29 | module m6 { 30 | var say = "a bird in hand > two in the bush"; 31 | var html = htmlEscape `
I would just like to say : ${say}
` 32 | 33 | // a sample tag function 34 | function htmlEscape(literals, ...placeholders) { 35 | let result = ""; 36 | 37 | // Interleave the literals with the placeholders 38 | for (let i = 0; i < placeholders.length; i++) { 39 | result += literals[i]; 40 | result += placeholders[i] 41 | .replace(/&/g, '&') 42 | .replace(/"/g, '"') 43 | .replace(/'/g, ''') 44 | .replace(//g, '>'); 46 | } 47 | 48 | // add the last literal 49 | result += literals[literals.length - 1]; 50 | return result; 51 | } 52 | console.log(html); 53 | } -------------------------------------------------------------------------------- /code/es6/test.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeFiction/typescript-book/a5b2250c7332fe10b04a281e3aad19d75bf0aea4/code/es6/test.js -------------------------------------------------------------------------------- /code/es6/test.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeFiction/typescript-book/a5b2250c7332fe10b04a281e3aad19d75bf0aea4/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/freshness/freshness.js: -------------------------------------------------------------------------------- 1 | exports.foo = 123; 2 | var first; 3 | (function (first) { 4 | function logName(something) { 5 | console.log(something.name); 6 | } 7 | var person = { name: 'matt', job: 'being awesome' }; 8 | var animal = { name: 'cow', diet: 'vegan, but has milk of own species' }; 9 | var random = { note: "I don't have a name property" }; 10 | logName(person); 11 | logName(animal); 12 | logName(random); 13 | })(first || (first = {})); 14 | var second; 15 | (function (second) { 16 | function logName(something) { 17 | console.log(something.name); 18 | } 19 | logName({ name: 'matt' }); 20 | logName({ name: 'matt', job: 'being awesome' }); 21 | })(second || (second = {})); 22 | var second; 23 | (function (second) { 24 | function logIfHasName(something) { 25 | if (something.name) { 26 | console.log(something.name); 27 | } 28 | } 29 | var person = { name: 'matt', job: 'being awesome' }; 30 | var animal = { name: 'cow', diet: 'vegan, but has milk of own species' }; 31 | var random = { note: "I don't have a name property" }; 32 | logIfHasName(person); 33 | logIfHasName(animal); 34 | logIfHasName(random); 35 | logIfHasName({ neme: 'I just misspelled name to neme' }); 36 | })(second || (second = {})); 37 | -------------------------------------------------------------------------------- /code/types/freshness/freshness.ts: -------------------------------------------------------------------------------- 1 | export var foo = 123; 2 | 3 | 4 | module first { 5 | function logName(something: { name: string }) { 6 | console.log(something.name); 7 | } 8 | 9 | var person = { name: 'matt', job: 'being awesome' }; 10 | var animal = { name: 'cow', diet: 'vegan, but has milk of own species' }; 11 | var random = { note: `I don't have a name property` }; 12 | 13 | logName(person); // okay 14 | logName(animal); // okay 15 | logName(random); // Error : property `name` is missing 16 | } 17 | 18 | module second { 19 | function logName(something: { name: string }) { 20 | console.log(something.name); 21 | } 22 | 23 | logName({ name: 'matt' }); // okay 24 | logName({ name: 'matt', job: 'being awesome' }); // Error: object literals must only specify known properties. `job` is excessive here. 25 | } 26 | 27 | 28 | module second { 29 | function logIfHasName(something: { name?: string }) { 30 | if (something.name) { 31 | console.log(something.name); 32 | } 33 | } 34 | var person = { name: 'matt', job: 'being awesome' }; 35 | var animal = { name: 'cow', diet: 'vegan, but has milk of own species' }; 36 | var random = { note: `I don't have a name property` }; 37 | 38 | logIfHasName(person); // okay 39 | logIfHasName(animal); // okay 40 | logIfHasName(random); // okay 41 | logIfHasName({neme: 'I just misspelled name to neme'}); // Error: object literals must only specify known properties. `neme` is excessive here. 42 | } 43 | -------------------------------------------------------------------------------- /code/types/freshness/index-signatures.js: -------------------------------------------------------------------------------- 1 | var a; 2 | (function (a) { 3 | var foo = {}; 4 | foo['Hello'] = 'World'; 5 | console.log(foo['Hello']); 6 | })(a || (a = {})); 7 | var b; 8 | (function (b) { 9 | var Foo = (function () { 10 | function Foo(message) { 11 | this.message = message; 12 | } 13 | ; 14 | Foo.prototype.log = function () { 15 | console.log(this.message); 16 | }; 17 | return Foo; 18 | }()); 19 | var foo = {}; 20 | foo['Hello'] = new Foo('World'); 21 | foo['Hello'].log(); 22 | })(b || (b = {})); 23 | var c; 24 | (function (c) { 25 | var obj = { 26 | toString: function () { 27 | console.log('toString called'); 28 | return 'Hello'; 29 | } 30 | }; 31 | var foo = {}; 32 | foo[obj] = 'World'; 33 | console.log(foo[obj]); 34 | console.log(foo['Hello']); 35 | })(c || (c = {})); 36 | var d; 37 | (function (d) { 38 | var foo = ['World']; 39 | console.log(foo[0]); 40 | })(d || (d = {})); 41 | var e; 42 | (function (e) { 43 | var obj = { 44 | toString: function () { 45 | return 'Hello'; 46 | } 47 | }; 48 | var foo = {}; 49 | foo[obj] = 'World'; 50 | foo[obj.toString()] = 'World'; 51 | })(e || (e = {})); 52 | var f; 53 | (function (f) { 54 | var obj = { message: 'Hello' }; 55 | var foo = {}; 56 | foo[obj] = 'World'; 57 | console.log(foo["[object Object]"]); 58 | })(f || (f = {})); 59 | var f; 60 | (function (f) { 61 | console.log((1).toString()); 62 | console.log((2).toString()); 63 | })(f || (f = {})); 64 | var g; 65 | (function (g) { 66 | var foo = {}; 67 | foo['a'] = { message: 'some message' }; 68 | foo['a'] = { messages: 'some message' }; 69 | foo['a'].message; 70 | foo['a'].messages; 71 | })(g || (g = {})); 72 | var mustConform2; 73 | (function (mustConform2) { 74 | var foo = { x: 1, y: 2 }; 75 | foo['x']; 76 | var x = 'x'; 77 | foo[x]; 78 | })(mustConform2 || (mustConform2 = {})); 79 | -------------------------------------------------------------------------------- /code/types/freshness/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.5.0-beta", 3 | "compilerOptions": { 4 | "target": "es5", 5 | "module": "commonjs", 6 | "isolatedModules": false, 7 | "jsx": "react", 8 | "experimentalDecorators": true, 9 | "emitDecoratorMetadata": true, 10 | "declaration": false, 11 | "noImplicitAny": false, 12 | "removeComments": true, 13 | "noLib": false, 14 | "preserveConstEnums": true, 15 | "suppressImplicitAnyIndexErrors": true 16 | }, 17 | "filesGlob": [ 18 | "./**/*.ts", 19 | "./**/*.tsx", 20 | "!./node_modules/**/*" 21 | ], 22 | "files": [ 23 | "./freshness.ts", 24 | "./index-signatures.ts" 25 | ], 26 | "atom": { 27 | "rewriteTsconfig": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /code/types/functions.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var parameter; 3 | (function (parameter) { 4 | var sampleVariable; 5 | function foo(sampleParameter) { } 6 | })(parameter || (parameter = {})); 7 | var returnType; 8 | (function (returnType) { 9 | function foo(sample) { 10 | return sample; 11 | } 12 | })(returnType || (returnType = {})); 13 | var inferred; 14 | (function (inferred) { 15 | function foo(sample) { 16 | return sample; 17 | } 18 | })(inferred || (inferred = {})); 19 | var misspelled; 20 | (function (misspelled) { 21 | function foo() { 22 | return { fou: 'John Doe' }; 23 | } 24 | sendAsJSON(foo()); 25 | })(misspelled || (misspelled = {})); 26 | var optional; 27 | (function (optional) { 28 | function foo(bar, bas) { 29 | } 30 | foo(123); 31 | foo(123, 'hello'); 32 | })(optional || (optional = {})); 33 | var optionalDefault; 34 | (function (optionalDefault) { 35 | function foo(bar, bas) { 36 | if (bas === void 0) { bas = 'world'; } 37 | console.log(bar, bas); 38 | } 39 | foo(123); 40 | foo(123, 'hello'); 41 | })(optionalDefault || (optionalDefault = {})); 42 | var overloads; 43 | (function (overloads) { 44 | function padding(a, b, c, d) { 45 | if (b === undefined && c === undefined && d === undefined) { 46 | b = c = d = a; 47 | } 48 | else if (c === undefined && d === undefined) { 49 | c = a; 50 | d = b; 51 | } 52 | return { 53 | top: a, 54 | right: b, 55 | bottom: c, 56 | left: d 57 | }; 58 | } 59 | overloads.padding = padding; 60 | })(overloads || (overloads = {})); 61 | var overloadsDone; 62 | (function (overloadsDone) { 63 | function padding(a, b, c, d) { 64 | if (b === undefined && c === undefined && d === undefined) { 65 | b = c = d = a; 66 | } 67 | else if (c === undefined && d === undefined) { 68 | c = a; 69 | d = b; 70 | } 71 | return { 72 | top: a, 73 | right: b, 74 | bottom: c, 75 | left: d 76 | }; 77 | } 78 | overloadsDone.padding = padding; 79 | })(overloadsDone || (overloadsDone = {})); 80 | -------------------------------------------------------------------------------- /code/types/functions.ts: -------------------------------------------------------------------------------- 1 | export namespace asdfasdfasdfasdflkjasdflkjasdflkjasdflkjasdf { 2 | } 3 | 4 | namespace parameter { 5 | // variable annotation 6 | var sampleVariable: { bar: number } 7 | 8 | // function parameter 9 | function foo(sampleParameter: { bar: number }) { } 10 | } 11 | 12 | namespace returnType { 13 | interface Foo { 14 | foo: string; 15 | } 16 | 17 | // Return type annotated as `: Foo` 18 | function foo(sample: Foo) { 19 | return sample; 20 | } 21 | } 22 | 23 | namespace inferred { 24 | interface Foo { 25 | foo: string; 26 | } 27 | 28 | function foo(sample: Foo) { 29 | return sample; // inferred return type 'Foo' 30 | } 31 | } 32 | 33 | namespace misspelled { 34 | function foo() { 35 | return { fou: 'John Doe' }; // You might not find this misspelling `foo` till its too late 36 | } 37 | 38 | sendAsJSON(foo()); 39 | } 40 | 41 | namespace optional { 42 | function foo(bar: number, bas?: string): void { 43 | // .. 44 | } 45 | 46 | foo(123); 47 | foo(123, 'hello'); 48 | } 49 | 50 | namespace optionalDefault { 51 | function foo(bar: number, bas: string = 'world') { 52 | console.log(bar, bas); 53 | } 54 | 55 | foo(123); // 123, world 56 | foo(123, 'hello'); // 123, hello 57 | } 58 | 59 | namespace overloads { 60 | export function padding(a: number, b?: number, c?: number, d?: any) { 61 | if (b === undefined && c === undefined && d === undefined) { 62 | b = c = d = a; 63 | } 64 | else if (c === undefined && d === undefined) { 65 | c = a; 66 | d = b; 67 | } 68 | return { 69 | top: a, 70 | right: b, 71 | bottom: c, 72 | left: d 73 | }; 74 | } 75 | } 76 | 77 | namespace overloadsDone { 78 | export function padding(all: number); 79 | export function padding(topAndBottom: number, leftAndRight: number); 80 | export function padding(top: number, right: number, bottom: number, left: number); 81 | export function padding(a: number, b?: number, c?: number, d?: number) { 82 | if (b === undefined && c === undefined && d === undefined) { 83 | b = c = d = a; 84 | } 85 | else if (c === undefined && d === undefined) { 86 | c = a; 87 | d = b; 88 | } 89 | return { 90 | top: a, 91 | right: b, 92 | bottom: c, 93 | left: d 94 | }; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /code/types/generics.js: -------------------------------------------------------------------------------- 1 | var aaa; 2 | (function (aaa) { 3 | var Queue = (function () { 4 | function Queue() { 5 | var _this = this; 6 | this.data = []; 7 | this.push = function (item) { return _this.data.push(item); }; 8 | this.pop = function () { return _this.data.shift(); }; 9 | } 10 | return Queue; 11 | }()); 12 | var queue = new Queue(); 13 | queue.push(0); 14 | queue.push("1"); 15 | console.log(queue.pop().toPrecision(1)); 16 | console.log(queue.pop().toPrecision(1)); 17 | })(aaa || (aaa = {})); 18 | var bbb; 19 | (function (bbb) { 20 | var QueueNumber = (function () { 21 | function QueueNumber() { 22 | var _this = this; 23 | this.data = []; 24 | this.push = function (item) { return _this.data.push(item); }; 25 | this.pop = function () { return _this.data.shift(); }; 26 | } 27 | return QueueNumber; 28 | }()); 29 | var queue = new QueueNumber(); 30 | queue.push(0); 31 | queue.push("1"); 32 | })(bbb || (bbb = {})); 33 | var ccc; 34 | (function (ccc) { 35 | var Queue = (function () { 36 | function Queue() { 37 | var _this = this; 38 | this.data = []; 39 | this.push = function (item) { return _this.data.push(item); }; 40 | this.pop = function () { return _this.data.shift(); }; 41 | } 42 | return Queue; 43 | }()); 44 | var queue = new Queue(); 45 | queue.push(0); 46 | queue.push("1"); 47 | })(ccc || (ccc = {})); 48 | -------------------------------------------------------------------------------- /code/types/generics.ts: -------------------------------------------------------------------------------- 1 | module aaa { 2 | class Queue { 3 | private data = []; 4 | push = (item) => this.data.push(item); 5 | pop = () => this.data.shift(); 6 | } 7 | 8 | const queue = new Queue(); 9 | queue.push(0); 10 | queue.push("1"); // Ops 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 | -------------------------------------------------------------------------------- /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/CodeFiction/typescript-book/a5b2250c7332fe10b04a281e3aad19d75bf0aea4/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 | -------------------------------------------------------------------------------- /code/types/migrating/migrating.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeFiction/typescript-book/a5b2250c7332fe10b04a281e3aad19d75bf0aea4/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/CodeFiction/typescript-book/a5b2250c7332fe10b04a281e3aad19d75bf0aea4/cover.jpg -------------------------------------------------------------------------------- /docs/async-await.md: -------------------------------------------------------------------------------- 1 | ## Asenkron Bekleme 2 | Şöyle bir deney kurguladığımızı varsayalım, Javascript çalışma zamanında `await` anahtar kelimesi bir `promise`(söz) ile birlikte görüldüğü anda kodun çalışması duraksayabilir ve sadece verilen sözün sonuca ulaşması tamamlandıktan sonra -sadece bir kerelik- çalışmaya kaldığı yerden devam eder. 3 | 4 | ```ts 5 | //Aşağıda gördüğünüz gerçek bir kod parçası değildir 6 | async function foo() { 7 | try { 8 | var val = await getMeAPromise(); 9 | console.log(val); 10 | } 11 | catch(err) { 12 | console.log('Error: ', err.message); 13 | } 14 | } 15 | 16 | ``` 17 | Verilen söz bir sonuca ulaştığında program çalışmaya devam eder, 18 | * Eğer verilen söz yerine getirildiyse `await` verilen sözün sonucunu dönecektir, 19 | * Eğer verilen söz yerine getirilmediyse (reddedildiyse), çalışma zamanında yakalayabileceğimiz bir hata senkron olarak fırlatılacaktır 20 | 21 | Bu yaklaşım asenkron programlamayı bir anda senkron programlama gibi kolay bir hale getiriyor.Bu deney için üç bileşen gereklidir. 22 | * *Fonksiyonları duraksatabilme* kabiliyeti. 23 | * Fonksiyonun içerisine *bir değer koyabilme* kabiliyeti. 24 | * Fonksiyonun içerisinden *bir istisna fırlatabilme* kabiliyeti. 25 | 26 | İşte bu saydıklarımız tam olarak *oluşturucular*ın yapmamıza olanak tanıdığı şey. Aslında bahsettiğimiz deney bir kurgu değil gerçeğin ta kendisidir ve Javascript / Typescript dünyasında `asenkron`/`bekle` uyarlaması olarak ifade edilir.Bu uyarlama perdenin arkasında oluşturucuları kullanır. 27 | 28 | 29 | ### Oluşturulmuş JavaScript 30 | Bunu tamamen anlamak zorunda değilsiniz ama [oluşturucuları][generators] okursanız oldukça basit olduğunu göreceksiniz. `foo` fonksiyonu aşağıdaki gibi basit bir şekilde paketlenebilir: 31 | 32 | ```ts 33 | const foo = sozAlmakicinPaketle(function* () { 34 | try { 35 | var val = yield banaSozVer(); 36 | console.log(val); 37 | } 38 | catch(err) { 39 | console.log('Error: ', err.message); 40 | } 41 | }) 42 | ``` 43 | `sozAlmakicinPaketle`'nin `oluşturucuyu` almak için sadece oluşturucu fonksiyonu çağırdığı bir durumda; daha sonra `generator.next()` ifadesi çağırılır, eğer dönen değer bir `söz` ise, `generator.next(result)` veya `generator.throw(error)` ifadelerinden biri duruma göre `then` veya `catch` ile yakalanarak işlem sonlandırılır. 44 | 45 | 46 | [generators]:./generators.md 47 | -------------------------------------------------------------------------------- /docs/classes-extensibility.md: -------------------------------------------------------------------------------- 1 | #### Sınıf genişletilebilirliği 2 | 3 | İnsanlar sıklıkla diğer JavaScript kütüphanelerindeki sınıflara özellikler ekler. İşte basit bir JavaScript örneği: 4 | 5 | ```js 6 | // Asıl Kütüphane 7 | function Foo {} 8 | 9 | // Yeni eleman özellikleri eklemek için üçüncü taraf (third party) uzantısı 10 | ``` 11 | -------------------------------------------------------------------------------- /docs/classes-super.md: -------------------------------------------------------------------------------- 1 | #### `super` 2 | 3 | Dikkat edin eğer alt sınıfınızda `super`çağrırsanız bu sizi aşağıda gösterildiği gibi `prototype`'a yönlendirecektir: 4 | 5 | ```ts 6 | class Base { 7 | log() { console.log('merha dünya'); } 8 | } 9 | 10 | class Child extends Base { 11 | log() { super.log() }; 12 | } 13 | ``` 14 | şunu üretir: 15 | 16 | ```js 17 | var Base = (function () { 18 | function Base() { 19 | } 20 | Base.prototype.log = function () { console.log('merha dünya'); }; 21 | return Base; 22 | })(); 23 | var Child = (function (_super) { 24 | __extends(Child, _super); 25 | function Child() { 26 | _super.apply(this, arguments); 27 | } 28 | Child.prototype.log = function () { _super.prototype.log.call(this); }; 29 | return Child; 30 | })(Base); 31 | 32 | ``` 33 | `_super.prototype.log.call(this)`'e dikkat. 34 | 35 | Bunun anlamı eleman özelliklerinizde `super`'i kullanamazsınız. Bunun yerine sadece `this` kullanmalısınız. 36 | 37 | ```ts 38 | class Base { 39 | log = () => { console.log('merhaba dünya'); } 40 | } 41 | 42 | class Child extends Base { 43 | logWorld() { this.log() }; 44 | } 45 | ``` 46 | 47 | `Base` ve `Child` sınıf arasında paylaşılan tek bir tane `this` olduğundan *farklı* adları kullanmanız gerektiğine dikkat edin (işte `log` ve `logWorld`). 48 | 49 | Ayrıca, `super`'i yanlış kullanmaya çalışırsanız TypeScript sizi uyaracaktır: 50 | 51 | ```ts 52 | module quz { 53 | class Base { 54 | log = () => { console.log('merhaba dünya'); } 55 | } 56 | 57 | class Child extends Base { 58 | // ERROR : only `public` and `protected` methods of base class are accessible via `super` 59 | // HATA : sadece üst sınıfın `public` ve `protected` metotları `super` ile erişilebilirdir 60 | logWorld() { super.log() }; 61 | } 62 | } 63 | ``` 64 | -------------------------------------------------------------------------------- /docs/compiler-options.md: -------------------------------------------------------------------------------- 1 | // mention Pinned comments 2 | 3 | ```ts 4 | /*! 5 | * License 6 | */ 7 | ``` 8 | -------------------------------------------------------------------------------- /docs/compiler/ast-tip-children.md: -------------------------------------------------------------------------------- 1 | ### AST Tip: Visit Children 2 | 3 | There is a utility function `ts.forEachChild` that allows you to visit all the child nodes of any Node in the AST. 4 | 5 | Here is simplified snippet of the source code to demonstrate how it functions: 6 | 7 | ```ts 8 | 9 | export function forEachChild(node: Node, cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T { 10 | if (!node) { 11 | return; 12 | } 13 | switch (node.kind) { 14 | case SyntaxKind.BinaryExpression: 15 | return visitNode(cbNode, (node).left) || 16 | visitNode(cbNode, (node).operatorToken) || 17 | visitNode(cbNode, (node).right); 18 | case SyntaxKind.IfStatement: 19 | return visitNode(cbNode, (node).expression) || 20 | visitNode(cbNode, (node).thenStatement) || 21 | visitNode(cbNode, (node).elseStatement); 22 | 23 | // .... lots more 24 | ``` 25 | 26 | Basically it checks `node.kind` and based on that assumes an interface offered by the `node` and calls the `cbNode` on the children. Note however that this function doesn't call `visitNode` for *all* children (e.g. SyntaxKind.SemicolonToken). If you want *all* the children of a node in the AST just call `.getChildren` member function of the `Node`. 27 | 28 | E.g. here is a function that prints the verbose `AST` of a node: 29 | 30 | ```ts 31 | function printAllChildren(node: ts.Node, depth = 0) { 32 | console.log(new Array(depth+1).join('----'), ts.syntaxKindToName(node.kind), node.pos, node.end); 33 | depth++; 34 | node.getChildren().forEach(c=> printAllChildren(c, depth)); 35 | } 36 | ``` 37 | 38 | We will see a sample usage of this function when we discuss the parser further. 39 | -------------------------------------------------------------------------------- /docs/compiler/ast-tip-syntaxkind.md: -------------------------------------------------------------------------------- 1 | ### AST Tip: SyntaxKind 2 | 3 | `SyntaxKind` is defined as a `const enum`, here is a sample: 4 | 5 | ```ts 6 | export const enum SyntaxKind { 7 | Unknown, 8 | EndOfFileToken, 9 | SingleLineCommentTrivia, 10 | // ... LOTS more 11 | ``` 12 | 13 | It's a `const enum` (a concept [we covered previously](../enums.md)) so that it gets *inlined* (e.g. `ts.SyntaxKind.EndOfFileToken` becomes `1`) and we don't get a dereferencing cost when working with AST. However the compiler is compiled with `--preserveConstEnums` compiler flag so that the enum *is still available at runtime*. So in JavaScript you can use `ts.SyntaxKind.EndOfFileToken` if you want. Additionally you can convert these enum members to display strings using the following function: 14 | 15 | ```ts 16 | export function syntaxKindToName(kind: ts.SyntaxKind) { 17 | return (ts).SyntaxKind[kind]; 18 | } 19 | ``` 20 | -------------------------------------------------------------------------------- /docs/compiler/ast-trivia.md: -------------------------------------------------------------------------------- 1 | ### Trivia 2 | Trivia (called that because its `trivial`) represent the parts of the source text that are largely insignificant for normal understanding of the code, such as whitespace, comments, and even conflict markers. Trivia is *not stored* in the AST (to keep it lightweight). However it can be fetched *on demand* using a few `ts.` APIs. Before we show them you need to understand 3 | 4 | #### Trivia Ownership 5 | In General: 6 | * A token owns any trivia after it on the *same* line *upto* the next token. 7 | * Any comment *after that line* is associated with the following token. 8 | 9 | For leading and ending comments in a file: 10 | * The first token in the source file gets all the initial trivia 11 | * The last sequence of trivia in the file is tacked onto the end-of-file token, which otherwise has zero width. 12 | 13 | The first token in the source file gets all the initial trivia, and the last sequence of trivia in the file is tacked onto the end-of-file token, which otherwise has zero width. 14 | 15 | #### Trivia APIs 16 | For most basic uses, comments are the "interesting" trivia. The comments that belong to a Node which can be fetched through the following functions: 17 | 18 | Function | Description 19 | ---------|------------ 20 | `ts.getLeadingCommentRanges` | Given the source text and position within that text, returns ranges of comments between the first line break following the given position and the token itself (probably most useful with `ts.Node.getFullStart`). 21 | `ts.getTrailingCommentRanges` | Given the source text and position within that text, returns ranges of comments until the first line break following the given position (probably most useful with `ts.Node.getEnd`). 22 | 23 | As an example, imagine this portion of a source file: 24 | 25 | ```ts 26 | debugger;/*hello*/ 27 | //bye 28 | /*hi*/ function 29 | ``` 30 | 31 | `getLeadingCommentRanges` for the `function` will only return the last 2 comments `//bye` and `/*hi*/`. 32 | 33 | Appropriately, calling `getTrailingCommentRanges` on the end of the debugger statement will extract the `/*hello*/` comment. 34 | 35 | #### Token Start/Full Start 36 | Nodes have what is called a "token start" and a "full start". 37 | 38 | * Token Start: the more natural version, which is the position in file where the text of a token begins 39 | * Full Start: the point at which the scanner began scanning since the last significant token 40 | 41 | AST nodes have an API for `getStart` and `getFullStart`. In the following example: 42 | 43 | ```ts 44 | debugger;/*hello*/ 45 | //bye 46 | /*hi*/ function 47 | ``` 48 | for `function` the token start is at `function` whereas *full* start is at `/*hello*/`. Note that full start even includes the trivia that would otherwise be owned by the previous node. 49 | -------------------------------------------------------------------------------- /docs/compiler/ast.md: -------------------------------------------------------------------------------- 1 | ## Node 2 | The basic building block of the Abstract Syntax Tree (AST). In general node represent non-terminals in the language grammar; some terminals are kept in the tree such as identifiers and literals. 3 | 4 | Two key things make up an AST node documentation. Its `SyntaxKind` which identifies it within the AST and its `interface`, the API the node provides when instantiated for the AST. 5 | 6 | Here are a few key `interface Node` members: 7 | * `TextRange` members that identify the node's `start` and `end` in the source file. 8 | * `parent?: Node` the parent of the node in the AST. 9 | 10 | There are other additional members for node flags and modifiers etc. that you can lookup by searching `interface Node` in the source code but the ones we mentioned are vital for node traversal. 11 | 12 | ## SourceFile 13 | 14 | * `SyntaxKind.SourceFile` 15 | * `interface SourceFile`. 16 | 17 | Each `SourceFile` is a top-level AST node that is contained in the `Program`. 18 | -------------------------------------------------------------------------------- /docs/compiler/binder-declarations.md: -------------------------------------------------------------------------------- 1 | ### Symbols and Declarations 2 | Linking between a `node` and a `symbol` is performed by a few functions. One function that is used to bind the `SourceFile` node to the source file Symbol (in case of an external module) is the `addDeclarationToSymbol` function 3 | 4 | Note : the `Symbol` for an external module source file is setup as `flags : SymbolFlags.ValueModule` and `name: '"' + removeFileExtension(file.fileName) + '"'`). 5 | 6 | ```ts 7 | function addDeclarationToSymbol(symbol: Symbol, node: Declaration, symbolFlags: SymbolFlags) { 8 | symbol.flags |= symbolFlags; 9 | 10 | node.symbol = symbol; 11 | 12 | if (!symbol.declarations) { 13 | symbol.declarations = []; 14 | } 15 | symbol.declarations.push(node); 16 | 17 | if (symbolFlags & SymbolFlags.HasExports && !symbol.exports) { 18 | symbol.exports = {}; 19 | } 20 | 21 | if (symbolFlags & SymbolFlags.HasMembers && !symbol.members) { 22 | symbol.members = {}; 23 | } 24 | 25 | if (symbolFlags & SymbolFlags.Value && !symbol.valueDeclaration) { 26 | symbol.valueDeclaration = node; 27 | } 28 | } 29 | ``` 30 | 31 | The important linking portions: 32 | * creates a link to the Symbol from the AST node (`node.symbol`). 33 | * add the node as *one of* the declarations of the Symbol (`symbol.declarations`). 34 | 35 | #### Declaration 36 | Declaration is just a `node` with an optional name. In `types.ts` 37 | 38 | ```ts 39 | interface Declaration extends Node { 40 | _declarationBrand: any; 41 | name?: DeclarationName; 42 | } 43 | ``` 44 | -------------------------------------------------------------------------------- /docs/compiler/binder-diagnostics.md: -------------------------------------------------------------------------------- 1 | ### Binder Error Reporting 2 | 3 | Binding errors are added to the sourceFile's list of `bindDiagnostics`. 4 | 5 | An example error detected during binding is the use of `eval` or `arguments` as a variable name in `use strict` scenario. The relevant code is presented in its entirety below (`checkStrictModeEvalOrArguments` is called from multiple places, call stacks originating from `bindWorker` which calls different functions for different node `SyntaxKind`): 6 | 7 | ```ts 8 | function checkStrictModeEvalOrArguments(contextNode: Node, name: Node) { 9 | if (name && name.kind === SyntaxKind.Identifier) { 10 | let identifier = name; 11 | if (isEvalOrArgumentsIdentifier(identifier)) { 12 | // We check first if the name is inside class declaration or class expression; if so give explicit message 13 | // otherwise report generic error message. 14 | let span = getErrorSpanForNode(file, name); 15 | file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, 16 | getStrictModeEvalOrArgumentsMessage(contextNode), identifier.text)); 17 | } 18 | } 19 | } 20 | 21 | function isEvalOrArgumentsIdentifier(node: Node): boolean { 22 | return node.kind === SyntaxKind.Identifier && 23 | ((node).text === "eval" || (node).text === "arguments"); 24 | } 25 | 26 | function getStrictModeEvalOrArgumentsMessage(node: Node) { 27 | // Provide specialized messages to help the user understand why we think they're in 28 | // strict mode. 29 | if (getContainingClass(node)) { 30 | return Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode; 31 | } 32 | 33 | if (file.externalModuleIndicator) { 34 | return Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode; 35 | } 36 | 37 | return Diagnostics.Invalid_use_of_0_in_strict_mode; 38 | } 39 | ``` 40 | -------------------------------------------------------------------------------- /docs/compiler/binder-functions.md: -------------------------------------------------------------------------------- 1 | ### Binder function 2 | Two critical binder functions are `bindSourceFile` and `mergeSymbolTable`. We will take a look at these next. 3 | 4 | #### `bindSourceFile` 5 | Basically checks if the `file.locals` is defined, if not it hands over to (a local function) `bind`. 6 | 7 | Note: `locals` is defined on `Node` and is of type `SymbolTable`. Note that `SourceFile` is also a `Node` (in fact a root node in the AST). 8 | 9 | TIP: local functions are used heavily within the TypeScript compiler. A local function very likely uses variables from the parent function (captured by closure). In the case of `bind` (a local function within `bindSourceFile`) it (or function it calls) will setup the `symbolCount` and `classifiableNames` among others, that are then stored on the returned `SourceFile`. 10 | 11 | #### `bind` 12 | Bind takes any `Node` (not just `SourceFile`). First thing it does is assign the `node.parent` (if `parent` variable has been setup ... which again is something the binder does during its processing within the `bindChildren` function), then hands off to `bindWorker` which does the *heavy* lifting. Finally it calls `bindChildren` (a function that simply stores the binder state e.g. current `parent` within its function local vars, then calls `bind` on each child, and then restores the binder state). Now let's look at `bindWorker` which is the more interesting function. 13 | 14 | #### `bindWorker` 15 | This function switches on `node.kind` (of type `SyntaxKind`) and delegates work to the appropriate `bindFoo` function (also defined within `binder.ts`). For example if the `node` is a `SourceFile` it calls (eventually and only if its an external file module) `bindAnonymousDeclaration` 16 | 17 | #### `bindFoo` functions 18 | There are few pattern common to `bindFoo` functions as well as some utility functions that these use. One function that is almost always used is the `createSymbol` function. It is presented in its entirety below: 19 | 20 | ```ts 21 | function createSymbol(flags: SymbolFlags, name: string): Symbol { 22 | symbolCount++; 23 | return new Symbol(flags, name); 24 | } 25 | ``` 26 | As you can see it is simply keeping the `symbolCount` (a local to `bindSourceFile`) up to date and creating the symbol with the specified parameters. 27 | -------------------------------------------------------------------------------- /docs/compiler/binder-symbolflags.md: -------------------------------------------------------------------------------- 1 | ### SymbolFlags 2 | Symbols have `SymbolFlags`. Below we eplain the meaning of the important ones 3 | 4 | #### ValueModule 5 | `ValueModule // Instantiated module` is the SymbolFlag used for `SourceFile` if it an external module. 6 | -------------------------------------------------------------------------------- /docs/compiler/binder.md: -------------------------------------------------------------------------------- 1 | ## Binder 2 | Most JavaScript transpilers out there are simpler than TypeScript in that they provide little in the way of code analysis. The typical JavaScript transpilers only have the following flow: 3 | 4 | ```ts 5 | SourceCode ~~Scanner~~> Tokens ~~Parser~~> AST ~~Emitter~~> JavaScript 6 | ``` 7 | 8 | While the above architecture is true as a simplified understand of TypeScript js generation, a key feature of TypeScript is its *Semantic* system. In order to assist type checking (performed by `checker`), the `binder` (in `binder.ts`) is used to connect the various parts of the source code into a coherent type system that can then be used by the `checker`. The main responsibility of the binder is to create the _Symbols_. 9 | 10 | ### Symbol 11 | Symbols connect declaration nodes in the AST to other declarations contributing to the same entity. Symbols are the basic building block of the Semantic system. The symbol constructor is defined in `core.ts` (and `binder` actually uses the `objectAllocator.getSymbolConstructor` to get its hands on it). Here is the contructor: 12 | 13 | ```ts 14 | function Symbol(flags: SymbolFlags, name: string) { 15 | this.flags = flags; 16 | this.name = name; 17 | this.declarations = undefined; 18 | } 19 | ``` 20 | 21 | `SymbolFlags` is a flag enum and is really used to identify additional classifications of the symbol (e.g the scope of a variable flags `FunctionScopedVariable` or `BlockScopedVariable` or others) 22 | 23 | ### Usage by Checker 24 | The `binder` is actually used internally by the type `checker` which in turn is used by the `program`. The simplified call stack looks like: 25 | ``` 26 | program.getTypeChecker -> 27 | ts.createTypeChecker (in checker)-> 28 | initializeTypeChecker (in checker) -> 29 | for each SourceFile `ts.bindSourceFile` (in binder) 30 | // followed by 31 | for each SourceFile `ts.mergeSymbolTable` (in checker) 32 | ``` 33 | The unit of work for the binder is a SourceFile. The `binder.ts` is driven by `checker.ts`. 34 | -------------------------------------------------------------------------------- /docs/compiler/checker-diagnostics.md: -------------------------------------------------------------------------------- 1 | ### Checker error reporting 2 | The checker uses the local `error` function to report errors. Here is the function: 3 | 4 | ```ts 5 | function error(location: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): void { 6 | let diagnostic = location 7 | ? createDiagnosticForNode(location, message, arg0, arg1, arg2) 8 | : createCompilerDiagnostic(message, arg0, arg1, arg2); 9 | diagnostics.add(diagnostic); 10 | } 11 | ``` 12 | -------------------------------------------------------------------------------- /docs/compiler/checker-global.md: -------------------------------------------------------------------------------- 1 | ### Global Namespace Merging 2 | Within `initializeTypeChecker` the following code exists : 3 | 4 | ```ts 5 | // Initialize global symbol table 6 | forEach(host.getSourceFiles(), file => { 7 | if (!isExternalModule(file)) { 8 | mergeSymbolTable(globals, file.locals); 9 | } 10 | }); 11 | ``` 12 | 13 | Which basically merges all the `global` symbols into the `let globals: SymbolTable = {};` (in `createTypeChecker`) SymbolTable. `mergeSymbolTable` primarily calls `mergeSymbol`. 14 | -------------------------------------------------------------------------------- /docs/compiler/checker.md: -------------------------------------------------------------------------------- 1 | ## Checker 2 | Like we mentioned before *checker* is the thing that makes TypeScript uniquely more powerful than *just another JavaScript transpiler*. The checker is located in `checker.ts` and at this moment it is 15k+ lines of code (largest part of the compiler). 3 | 4 | ### Usage by Program 5 | The `checker` is initialized by `program`. The following is a sampling of the call stack (we showed the same one when looking at `binder`): 6 | 7 | ``` 8 | program.getTypeChecker -> 9 | ts.createTypeChecker (in checker)-> 10 | initializeTypeChecker (in checker) -> 11 | for each SourceFile `ts.bindSourceFile` (in binder) 12 | // followed by 13 | for each SourceFile `ts.mergeSymbolTable` (in checker) 14 | ``` 15 | 16 | ### Association with Emitter 17 | True type checking happens once a call is made to `getDiagnostics`. This function is called e.g. once a request is made to `Program.emit`, in which case the checker returns an `EmitResolver` (progarm calls the checkers `getEmitResolver` function) which is just a set of functions local to `createTypeChecker`. We will mention this again when we look at the emitter. 18 | 19 | Here is the call stack right down to `checkSourceFile` (a function local to `createTypeChecker`). 20 | 21 | ``` 22 | program.emit -> 23 | emitWorker (program local) -> 24 | createTypeChecker.getEmitResolver -> 25 | // First call the following functions local to createTypeChecker 26 | call getDiagnostics -> 27 | getDiagnosticsWorker -> 28 | checkSourceFile 29 | 30 | // then 31 | return resolver 32 | (already initialized in createTypeChecker using a call to local createResolver()) 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/compiler/emitter.md: -------------------------------------------------------------------------------- 1 | ## Emitter 2 | There are two `emitters` provided with the TypeScript compiler: 3 | 4 | * `emitter.ts`: this is the emitter you are most likely to be interested in. Its the TS -> JavaScript emitter. 5 | * `declarationEmitter.ts`: this is the emitter used to create a *declaration file* (a `.d.ts`) for a *TypeScript source file* (a `.ts` file). 6 | 7 | We will look at `emitter.ts` in this section. 8 | 9 | ### Usage by `program` 10 | Program provides an `emit` function. This function primarily delegates to `emitFiles` function in `emitter.ts`. Here is the call stack: 11 | 12 | ``` 13 | Program.emit -> 14 | `emitWorker` (local in program.ts createProgram) -> 15 | `emitFiles` (function in emitter.ts) 16 | ``` 17 | One thing that the `emitWorker` provides to the emitter (via an argument to `emitFiles`) is an `EmitResolver`. `EmitResolver` is provided by the program's TypeChecker, basically it a subset of *local* functions from `createChecker`. 18 | -------------------------------------------------------------------------------- /docs/compiler/make-global.md: -------------------------------------------------------------------------------- 1 | ## Make TypeScript Global 2 | 3 | TypeScript is written using a `namespace ts`. And then the whole compiler is compiled into a single `typescript.js` file. If you want to copy over parts of the source code for exploration a great way to do that is to copy over the portions that you are exploring and then expose them to the global variable `ts`. 4 | 5 | A great way to play around with the TypeScript compiler is just to copy the TypeScript compiler source into a folder and then reference it as a `global` variable. 6 | -------------------------------------------------------------------------------- /docs/compiler/parser-functions.md: -------------------------------------------------------------------------------- 1 | ### Parser Functions 2 | 3 | As mentioned `parseSourceFile` sets up the initial state and passes the work onto `parseSourceFileWorker` function. 4 | 5 | #### `parseSourceFileWorker` 6 | 7 | Starts by creating a `SourceFile` AST node. Then it goes into parsing source code starting from the `parseStatements` function. Once that returns, it then completes the `SourceFile` node with additional information such as its `nodeCount`, `identifierCount` and such. 8 | 9 | #### `parseStatements` 10 | One of the most significant `parseFoo` style functions (a concept we cover next). It switches by the the current `token` returned from the scanner. E.g. if the current token is a `SemicolonToken` it will call out to `parseEmptyStatement` to create an AST node for an empty statement. 11 | 12 | ### Node creation 13 | 14 | The parser has a bunch of `parserFoo` functions with bodies that create `Foo` nodes. These are generally called (from other parser functions) at a time where a `Foo` node is expected. A typical sample of this process is the `parseEmptyStatement()` function which is used to parse out empty statements like `;;;;;;`. Here is the function in its entirety 15 | 16 | ```ts 17 | function parseEmptyStatement(): Statement { 18 | let node = createNode(SyntaxKind.EmptyStatement); 19 | parseExpected(SyntaxKind.SemicolonToken); 20 | return finishNode(node); 21 | } 22 | ``` 23 | 24 | It shows three critical functions `createNode`, `parseExpected` and `finishNode`. 25 | 26 | #### `createNode` 27 | The parser's `createNode` function `function createNode(kind: SyntaxKind, pos?: number): Node` is responsible for creating a Node, setting up its `SyntaxKind` as passed in, and set the initial position if passed in (or use the position from the current scanner state). 28 | 29 | #### `parseExpected` 30 | The parser's `parseExpected` function `function parseExpected(kind: SyntaxKind, diagnosticMessage?: DiagnosticMessage): boolean` will check that the current token in the parser state matches the desired `SyntaxKind`. If not it will either report the `diagnosticMessage` sent in or create a generic one of the form `foo expected`. It internally uses the `parseErrorAtPosition` function (which uses the scanning positions) to give good error reporting. 31 | 32 | ### `finishNode` 33 | The parser's `finishNode` function `function finishNode(node: T, end?: number): T` sets up the `end` position for the node and additional useful stuff like the `parserContextFlags` it was parsed under as well as if there were any errors before parsing this node (if there were then we cannot reuse this AST node in incremental parsing). 34 | -------------------------------------------------------------------------------- /docs/compiler/parser.md: -------------------------------------------------------------------------------- 1 | ## Parser 2 | The sourcecode for the TypeScript parser is located entirely in `parser.ts`. Scanner is *controlled* internally by the `Parser` to convert the source code to an AST. Here is a review of what the desired outcome is. 3 | 4 | ``` 5 | SourceCode ~~ scanner ~~> Token Stream ~~ parser ~~> AST 6 | ``` 7 | 8 | The parser is implemented as a singleton (similar reasons to `scanner`, don't want to recreate it if we can reinit it). It is actually implemented as `namespace Parser` which contains *state* variables for the Parser as well as a singleton `scanner`. As mentioned before it contains a `const scanner`. The parser functions manage this scanner. 9 | 10 | ### Usage by program 11 | Parser is driven indirectly by Program (indirectly as its actually by `CompilerHost` which we mentioned previously). Basically this is the simplified call stack: 12 | 13 | ``` 14 | Program -> 15 | CompilerHost.getSourceFile -> 16 | (global function parser.ts).createSourceFile -> 17 | Parser.parseSourceFile 18 | ``` 19 | 20 | The `parseSourceFile` not only primes the state for the Parser but also primes the state for the `scanner` by calling `initializeState`. It then goes on to parse the source file using `parseSourceFileWorker`. 21 | 22 | ### Sample Usage 23 | Before we dig too deep into the parser internals, here is a sample code that uses the TypeScript's parser to get the AST of a source file (using `ts.createSourceFile`), and then print it. 24 | 25 | `code/compiler/parser/runParser.ts` 26 | ```ts 27 | import * as ts from "ntypescript"; 28 | 29 | function printAllChildren(node: ts.Node, depth = 0) { 30 | console.log(new Array(depth + 1).join('----'), ts.syntaxKindToName(node.kind), node.pos, node.end); 31 | depth++; 32 | node.getChildren().forEach(c=> printAllChildren(c, depth)); 33 | } 34 | 35 | var sourceCode = ` 36 | var foo = 123; 37 | `.trim(); 38 | 39 | var sourceFile = ts.createSourceFile('foo.ts', sourceCode, ts.ScriptTarget.ES5, true); 40 | printAllChildren(sourceFile); 41 | ``` 42 | 43 | This will print out the following: 44 | 45 | ```ts 46 | SourceFile 0 14 47 | ---- SyntaxList 0 14 48 | -------- VariableStatement 0 14 49 | ------------ VariableDeclarationList 0 13 50 | ---------------- VarKeyword 0 3 51 | ---------------- SyntaxList 3 13 52 | -------------------- VariableDeclaration 3 13 53 | ------------------------ Identifier 3 7 54 | ------------------------ FirstAssignment 7 9 55 | ------------------------ FirstLiteralToken 9 13 56 | ------------ SemicolonToken 13 14 57 | ---- EndOfFileToken 14 14 58 | ``` 59 | This looks like a (very right sided) tree if you tilt your head to the left. 60 | -------------------------------------------------------------------------------- /docs/compiler/program.md: -------------------------------------------------------------------------------- 1 | ## Program 2 | 3 | Defined in `program.ts`. The compilation context ([a concept we covered previously](docs/project/compilation-context.md)) is represented within the TypeScript compiler as a `Program`. It consists of `SourceFile`s and compiler options. 4 | 5 | 6 | ### Usage of `CompilerHost` 7 | Its interaction mechanism with the OE: 8 | 9 | `Program` *-uses->* `CompilerHost` *-uses->* `System` 10 | 11 | The reason for having a `CompilerHost` as a point of indirection is that it allows it's interface to be more finely tuned for `Program` needs and not bother with OE needs (e.g. the `Program` doesn't care about `fileExists` a function provided by `System`). 12 | 13 | There are other users of `System` as well (e.g. tests). 14 | 15 | ### SourceFile 16 | 17 | The program provides an API to get the Source Files `getSourceFiles(): SourceFile[];`. Each is represented as a root-level node for an AST (called `SourceFile`). 18 | -------------------------------------------------------------------------------- /docs/const.md: -------------------------------------------------------------------------------- 1 | ### const 2 | 3 | `const` is a very welcomed addition offered by ES6 / TypeScript. It allows you to be immutable with variables. This is good from a documentation as well as a runtime perspective. To use const just replace `var` with `const`: 4 | 5 | ```ts 6 | const foo = 123; 7 | ``` 8 | 9 | > The syntax is much better (IMHO) than other languages that force the user to type something like `let constant foo` i.e. a variable + behavior specifier. 10 | 11 | `const` is a good practice for both readability and maintainability and avoids using *magic literals* e.g. 12 | 13 | ```ts 14 | // Low readability 15 | if (x > 10) { 16 | } 17 | 18 | // Better! 19 | const maxRows = 10; 20 | if (x > maxRows) { 21 | } 22 | ``` 23 | 24 | #### const declarations must be initialized 25 | The following is a compiler error: 26 | 27 | ```ts 28 | const foo; // ERROR: const declarations must be initialized 29 | ``` 30 | 31 | #### Left hand side of assignment cannot be a constant 32 | Constants are immutable after creation, so if you try to assign them to a new value it is a compiler error: 33 | 34 | ```ts 35 | const foo = 123; 36 | foo = 456; // ERROR: Left-hand side of an assignment expression cannot be a constant 37 | ``` 38 | 39 | #### Block Scoped 40 | A `const` is block scoped like we saw with [`let`](./let.md): 41 | 42 | ```ts 43 | const foo = 123; 44 | if (true) { 45 | const foo = 456; // Allowed as its a new variable limited to this `if` block 46 | } 47 | ``` 48 | 49 | #### Deep immutability 50 | A `const` works with object literals as well, as far as protecting the variable *reference* is concerned: 51 | 52 | ```ts 53 | const foo = { bar: 123 }; 54 | foo = { bar: 456 }; // ERROR : Left hand side of an assignment expression cannot be a constant 55 | ``` 56 | 57 | However it still allows sub properties of objects to be mutated, as shown below: 58 | 59 | ```ts 60 | const foo = { bar: 123 }; 61 | foo.bar = 456; // Allowed! 62 | console.log(foo); // { bar: 456 } 63 | ``` 64 | 65 | For this reason I recommend using `const` with literals or immutable data structures. 66 | -------------------------------------------------------------------------------- /docs/declaration.md: -------------------------------------------------------------------------------- 1 | analogy with c headers 2 | -------------------------------------------------------------------------------- /docs/errors/main.md: -------------------------------------------------------------------------------- 1 | # Sıkça Karşılaşılan Hatalar 2 | Bu bölümde kullanıcıların gerçek hayatta deneyimledikleri birkaç genel hata kodunu açıklayacağız. 3 | 4 | ## TS2304 5 | Örnek: 6 | > `Cannot find name ga (ga ismi bulunamıyor)` 7 | 8 | Muhtemelen `deklare (declare)` etmediğiniz üçüncü parti bir kütüphane (örneğin google analytics) kullanıyorsunuz. TypeScript sizi *yazım hatalarından* ve *değişkenleri deklare etmeden kullanmanızdan* korumaya çalışır, yani *çalışma zamanında varolan* harhangi bir şeye açık olmalısınız çünkü bazı dış kütüphaneleri dahil ediyorsunuz ([nasıl düzeltileceğine dair daha fazla bilgi][ambient]). 9 | 10 | ## TS2307 11 | Örnek: 12 | > `Cannot find module 'underscore' ('underscrore' modülü bulunamıyor)` 13 | 14 | Muhtemelen üçüncü parti bir kütüphaneyi (örneğin underscore) *modül* ([modüllere (modules) dair daha fazla bilgi][modules]) olarak kullanıyorsunuz ve bunun için içsel deklarasyon dosyanız yok ([içsel deklarasyona dair daha fazla bilgi][ambient]). 15 | 16 | ## TS1148 17 | Örnek: 18 | > Cannot compile modules unless the '--module' flag is provided ('--module' işareti sağlanmadığı sürece modüller derlenemez) 19 | 20 | [Modüller (modules) bölümü][modules]'ne göz atın. 21 | 22 | ## Arama indekslemesi için 23 | Bu kısmı görmezden gelebilirsiniz. Bu kısım arama motoru indekslemesi için. 24 | 25 | > Kullanıcıların kullanmayı sevdiği ve hata vermeye eğilimli diğer modüller: 26 | * Cannot find name $ ($ ismi bulunamıyor) 27 | * Cannot find module jquery (jquery modülü bulunamıyor) 28 | 29 | [ambient]: ../types/ambient/d.ts.md 30 | [modules]: ../project/modules.md 31 | -------------------------------------------------------------------------------- /docs/for...of.md: -------------------------------------------------------------------------------- 1 | ### for...of 2 | Dizi öğelerinin yinelenmesi için `for...in` kullanılması, Javascript'e yeni başlayan geliştiricilerin karşılaştıkları yaygın bir hatadır. Dizi elemanları yerine verilen nesnenin *anahtarlarını*(*keys*) yineler. Aşağıdaki örnekte gösterilmiştir. `9,2,5` beklemenize rağmen, çıkan sonuç `0,1,2` dizinleridir: 3 | 4 | ```ts 5 | var someArray = [9, 2, 5]; 6 | for (var item in someArray) { 7 | console.log(item); // 0,1,2 8 | } 9 | ``` 10 | 11 | `for...of`'un TypeScript'te (ve ES6'da) olma sebeplerinden biri, işte budur. Örneğin, sıradaki dizi doğru bir biçimde yinelenmekte ve elemanları beklenildiği gibi çıkmaktadır: 12 | 13 | ```ts 14 | var someArray = [9, 2, 5]; 15 | for (var item of someArray) { 16 | console.log(item); // 9,2,5 17 | } 18 | ``` 19 | 20 | TypeScript, karakter dizimindeki karakterleri yinelemek için de `for...of` kullanmanıza imkan sağlar: 21 | 22 | ```ts 23 | var selam = "naber?"; 24 | for (var char of selam) { 25 | console.log(char); 26 | } 27 | // 'n' 28 | // 'a' 29 | // 'b' 30 | // 'e' 31 | // 'r' 32 | // '?' 33 | ``` 34 | 35 | #### JS Oluşturulması 36 | TypeScript, ES6 öncesi için `for (var i = 0; i < list.length; i++)` benzeri standart bir döngü oluşturur. Önceki örneğimizin Javascript'te oluşturulmuş hali, şu şekildedir: 37 | ```ts 38 | var someArray = [9, 2, 5]; 39 | for (var item of someArray) { 40 | console.log(item); 41 | } 42 | 43 | // şuna dönüşür // 44 | 45 | for (var _i = 0; _i < someArray.length; _i++) { 46 | var item = someArray[_i]; 47 | console.log(item); 48 | } 49 | ``` 50 | Gördüğünüz gibi `for...of` kullandığınızda *maksadınız* daha açıktır. Ayrıca yazdığınız kod miktarı (ve kullandığınız değişken isimleri) azalır. 51 | 52 | #### Kısıtlamalar 53 | Eğer ES6 veya üstünü hedeflemiyorsanız, oluşturulan kod, nesnede `length` özelliği olduğunu varsayar ve nesneye dizin kullanarak erişir, örneğin; `obj[2]`. Bu yüzden eski JS motorları sadece `string` ve `array` destekler. 54 | 55 | Eğer dizi veya karakter dizimi kullanmazsınız, TypeScript bunu görür ve *"dizi veya karakter dizimi tipinde değil"* hatası verir; 56 | ```ts 57 | let articleParagraphs = document.querySelectorAll("article > p"); 58 | //Hata: Nodelist is not an array type or a string type 59 | for (let paragraph of articleParagraphs) { 60 | paragraph.classList.add("read"); 61 | } 62 | ``` 63 | `for...of`'u sadece dizi veya karakter dizimi olduğunu *bildiğiniz* şeylerde kullanın. Bu kısıtlamanın TypeScript'in ileriki sürümlerinde kaldırılabileceğini de göz önünde bulundurunuz. 64 | 65 | #### Özet 66 | Dizilerde yinelemeyi ne kadar kullandığınızı bilseniz şaşırırsınız. Bir dahaki denemenizde, `for...of`'a bir şans verin. Belki de kodunuzu gözden geçiren bir sonraki kişiyi mutlu edeceksiniz. -------------------------------------------------------------------------------- /docs/future-javascript.md: -------------------------------------------------------------------------------- 1 | # Geleceğin Javascript'i: Şimdi 2 | Typescript'in istenilen bir ürün olmasının nedenlerinden biri ES6 ve güncel (ES3 ve ES5 seviyesi) Javascript motorlarının (güncel tarayıcılar ve NodeJS) ötesindeki özellikleri desteklemesidir. Neden bu özelliklerin faydalı olduğunu ve devamında Typescript'te nasıl uygulandıklarını derinlemesine inceleyeceğiz. 3 | 4 | Not: Bu özelliklerin tamamı Javascript'e gözle görülür katkı sağlamasa da kod organizasyonu ve bakımını önemli ölçüde geliştirecektir. Ayrıca bilmenizde fayda var; size mantıklı gelmeyen yapıları yoksaymakta serbestsiniz. Her ne kadar, eninde sonunda çoğunu kullanacak olsanız da ;) 5 | -------------------------------------------------------------------------------- /docs/getting-started.md: -------------------------------------------------------------------------------- 1 | * [TypeScript'e Başlarken](#typescripte-başlarken) 2 | * [TypeScript Sürümleri](#typescript-sürümleri) 3 | * [Örneklerin Kaynak Kodlarını İndirmek](#Örneklerin-kaynak-kodlarını-İndirmek) 4 | 5 | # TypeScript'e Başlarken 6 | 7 | TypeScript, JavaScript'e derlenmektedir. Aslında JavaScript sunucu tarafında ya da tarayıcıda çalışacak olan kodun kendisidir. Dolayısıyla uygulamanızı çalıştırabilmek için aşağıdaki kurulumları tamamlamanız gerekmektedir: 8 | 9 | * TypeScript derleyicisi ([Kaynak Kodu](https://github.com/Microsoft/TypeScript/) ve [NPM](https://www.npmjs.com/package/typescript) paketi mevcuttur.) 10 | * Bir TypeScript editörü (Notepad ya da diğer birçok editörden bir tanesini kullanabilirsiniz. Örneğin bulut tabanlı olan [alm](http://alm.tools)'nin güzel bir örnek olması yanında [bir çok farklı editör de mevcuttur]( https://github.com/Microsoft/TypeScript/wiki/TypeScript-Editor-Support).) 11 | 12 | 13 | ![](https://raw.githubusercontent.com/alm-tools/alm-tools.github.io/master/screens/main.png) 14 | 15 | 16 | ## TypeScript Sürümleri 17 | 18 | Kitapta anlatacağımız bazı yeni özellikler henüz *kararlı* bir TypeScript derleyicisi tarafından desteklenmemektedir. Hatta bazıları henüz bir sürüm numarası ile bile ilişkilendirilmemiş olabilir. 19 | 20 | TypeScript derleyicisini aşağıdaki komut ile bilgisayarınıza kurabilirsiniz, 21 | 22 | ``` 23 | npm install -g typescript@next 24 | ``` 25 | 26 | Bundan sonra komut satırına yazılacak olan `tsc` komutu, en son ve en iyi versiyonu olarak kullanılabilir olacaktır. Birçok editör bu sürümü desteklemektedir. Örneğin, 27 | 28 | * `alm` her zaman son sürümünde en güncel TypeScript sürümü ile yayınlanmaktadır. 29 | * Eğer `vscode` kullanıyorsanız aşağıdaki içeriğe sahip bir `.vscode/settings.json` dosyası oluşturursanız son sürümü kullanacaktır: 30 | 31 | ```json 32 | { 33 | "typescript.tsdk": "./node_modules/typescript/lib" 34 | } 35 | ``` 36 | 37 | ## Örneklerin Kaynak Kodlarını İndirmek 38 | Kitabın içerisindeki örneklerin kaynak kodlarına GitHub üzerinden https://github.com/Codefiction/typescript-book/tree/master/code adresinden ulaşabilirsiniz. Kodların büyük bir kısmı alm'ye kopyalandığında hemen çalıştırılabilir durumdadır. 39 | Ek bir kurulum gerektiren örnekler (örneğin npm modülleri) için kod bloğu anlatılmadan önce ilişkili kod ile ilgili aşağıdaki gibi bir referans verilecektir. 40 | 41 | `bu/referans/olacak/kodun/adresi.ts` 42 | ```ts 43 | // Örneklerde anlatılan kodun kendisi 44 | ``` 45 | 46 | Geliştirme ortamının kurulumunu tamamladığımıza göre artık TypeScript diline giriş yapabiliriz. 47 | -------------------------------------------------------------------------------- /docs/javascript/awful.md: -------------------------------------------------------------------------------- 1 | # JavaScript'in kötü tarafları 2 | 3 | İşte JavaScript'in bilmeniz gereken bazı kötü (anlaşılmaz) tarafları. 4 | 5 | > Not: TypeScript, JavaScript'in süpersetidir. Aslında derleyiciler/IDE'ler tarafından kullanılan dokümantasyonlu halidir ;) 6 | 7 | ## Null ve Undefined 8 | 9 | Gerçek şu ki ikisiyle de uğraşmanız gerekecektir. İkisi için de `==` ile kontrol edelim. 10 | 11 | ```ts 12 | /// bar aşağıdakilerden biri iken `foo.bar == undefined` yaptığınızı düşünün: 13 | console.log(undefined == undefined); // true 14 | console.log(null == undefined); // true 15 | console.log(0 == undefined); // false 16 | console.log('' == undefined); // false 17 | console.log(false == undefined); // false 18 | ``` 19 | Tavsiyem `undefined` veya `null`, ikisi için de `== null` ile kontrol etmelisiniz. Genellikle bu ikisi arasında bir ayrım yapmak istemezsiniz. 20 | 21 | ## undefined 22 | 23 | Hatırlarsanız `== null`'u nasıl kullanmanız gerektiğini söylemiştim. Tabii ki kullanacaksınız (çünkü ben öyle söyledim ^). Kök seviyesindeki şeyler için kullanmayın. Katı modda (strict mode) eğer `foo` kullanırsanız ve `foo` tanımlanmamış (undefined) ise, `ReferenceError` **hatası** alırsınız ve tüm çağrı kümeniz bozulur. 24 | 25 | > Katı mod (strict mode) kullanmalısınız ... ve aslında TS derleyicisi eğer modül kullanırsanız sizin için bunu ekleyecektir ... daha fazlası kitabın ilerleyen bölümlerinde var yani şu anda açık şekilde anlamış olmanız gerekmez :) 26 | 27 | Yani bir değişkenin *global* düzeyde tanımlanıp tanımlanmadığını kontrol etmek için `typeof` kullanılır: 28 | 29 | ```ts 30 | if (typeof someglobal !== 'undefined') { 31 | // someglobal kullanımı şu anda güvenli 32 | console.log(someglobal); 33 | } 34 | ``` 35 | 36 | ## this 37 | 38 | Bir fonksiyon içindeki `this` anahtar sözcüğüne herhangi bir erişim, aslında fonksiyonun nasıl çağrıldığına göre kontrol edilir. Genellikle `çağrı bağlamı (calling context)` olarak bahsedilir. 39 | 40 | Aşağıdaki örnek bunu açıklamaktadır: 41 | 42 | ```ts 43 | function foo() { 44 | console.log(this); 45 | } 46 | 47 | foo(); // global olarak çıktı verir, örneğin tarayıcılardaki `window` 48 | let bar = { 49 | foo 50 | } 51 | bar.foo(); // `bar` üzerinde çağrıldığında `foo` olarak `bar` çıktısı verir 52 | ``` 53 | Bu nedenle `this` kullanımınızda dikkatli olun . Eğer çağırdığınız bağlamda gelen sınıfın icindeki `this`'ten kopmak isterseniz ok fonksiyonlarını kullanın, [daha fazlası][ok]. 54 | 55 | [ok]:../arrow-functions.md 56 | 57 | ## Sıradaki 58 | 59 | İşte bu. Bunlar JavaScript'in bazı yanlış anlaşılan parçalarıdır ve hala bu dilde yeni olan geliştiriciler için çeşitli hatalarla sonuçlanır 🌹. -------------------------------------------------------------------------------- /docs/javascript/closure.md: -------------------------------------------------------------------------------- 1 | ## Kapsanım 2 | 3 | JavaScript'in sahip olduğu en iyi şey kapsanımlardır. JavaScript'de bir fonksiyon dış faaliyet alanında tanımlanmış herhangi bir değişkene erişebilir. Kapsanımlar en iyi şekilde örneklerle açıklanabilir: 4 | 5 | ```ts 6 | function outerFunction(arg) { 7 | var variableInOuterFunction = arg; 8 | 9 | function bar() { 10 | console.log(variableInOuterFunction); // Dış faaliyet alanındaki bir değişkene erişim 11 | } 12 | 13 | // arg'ye erişim olduğunu göstermek için yerel fonksiyon çağrısı 14 | bar(); 15 | } 16 | 17 | outerFunction("merhaba kapsanım"); // merhaba kapsanım çıktısı üretir! 18 | ``` 19 | 20 | Gördüğünüz üzere iç fonksiyonun, dış faaliyet alanındaki değişkene (variableInOuterFunction) erişimi vardır. Dış fonksiyondaki değişkenler iç fonksiyon tarafından kapatılmıştır (veya bağlanmıştır). Bu nedenle terim **kapsanım**. Kendi içindeki kavram yeterince basit ve oldukça sezgisel. 21 | 22 | Şimdi en harika kısmı: *Dış fonksiyon geri döndükten sonra bile* iç fonksiyon, dış faaliyet alanındaki değişkenlere erişebilir. Bunun nedeni, değişkenlerin hala iç fonksiyona bağlı olması ve dış fonksiyona bağımlı olmamasıdır. Gelin tekrar örneğe bakalım: 23 | 24 | ```ts 25 | function outerFunction(arg) { 26 | var variableInOuterFunction = arg; 27 | return function() { 28 | console.log(variableInOuterFunction); 29 | } 30 | } 31 | 32 | var innerFunction = outerFunction("merhaba kapsanım!"); 33 | 34 | // outerFunction geri geldiğine dikkat edin 35 | innerFunction(); // merhaba kapsanım! çıktısı üretir 36 | ``` 37 | 38 | ### Harika olmasının sebebi 39 | Size nesneleri kolayca oluşturmanızı sağlar, örneğin açıklayıcı modül kalıbı: 40 | 41 | ```ts 42 | function createCounter() { 43 | let val = 0; 44 | return { 45 | increment() { val++ }, 46 | getVal() { return val } 47 | } 48 | } 49 | 50 | let counter = createCounter(); 51 | counter.increment(); 52 | console.log(counter.getVal()); // 1 53 | counter.increment(); 54 | console.log(counter.getVal()); // 2 55 | ``` 56 | 57 | Üst seviyede nodejs gibi bir şeyi mümkün kılan şey de budur (Kafanızda şekillenmediyse endişelenmeyin. Sonunda olacak 🌹): 58 | 59 | ```ts 60 | // Kavramı açıklamak için sözde kod (pseudo code) 61 | server.on(function handler(req, res) { 62 | loadData(req.id).then(function(data) { 63 | // `res` kapatıldı ve hazır 64 | res.send(data); 65 | }) 66 | }); 67 | ``` 68 | -------------------------------------------------------------------------------- /docs/javascript/recap.md: -------------------------------------------------------------------------------- 1 | # JavaScript'iniz TypeScript'tir. 2 | 3 | Bazı sözdiziminden JavaScript derleyicilerine kadar birçok rakip vardı (ve olmaya devam edecektir). TypeScript onlardan şu şekilde farklıdır *JavaScript'iniz TypeScript'tir*. İşte bir şema: 4 | 5 | ![](https://raw.githubusercontent.com/basarat/typescript-book/master/images/venn.png) 6 | 7 | Ancak bunun anlamı *JavaScript öğrenmeniz gerekir* (iyi haber şu ki *sizin **sadece** JavaScript öğrenmeniz gerekmektedir*). TypeScript sadece JavaScript'teki sunulan *iyi dökümantasyon'u* standartlaştırmaktadır. 8 | 9 | * Size yeni bir sözdizimi verilmesi hataların düzeltilmesine yardımcı olmaz (CoffeeScript, gözüm üzerinde). 10 | * Yeni bir dil oluşturmak sizi çalışma zamanı ortamlarınızdan ve topluluklarınızdan uzaklaşmanızı sağlar (Dart, gözüm üzerinde). 11 | 12 | TypeScript, dökümanlarla JavaScript'tir. 13 | 14 | ## JavaScript'i İyileştirmek 15 | 16 | TypeScript sizi hiç çalışmamış JavaScript parçalarından korumaya çalışacaktır ( Bu sebeple bunları hatırlamanıza gerek yok): 17 | 18 | ```ts 19 | [] + []; // JavaScript size "" sonucunu verecek (ki mantıklı olan), TypeScript ise hata 20 | 21 | // 22 | // JavaScript'te anlamsız olan diğer konular 23 | // - çalışma zamanı hatası vermez (hata ayıklamayı zorlaştırıyor) 24 | // - ama TypeScript derleme zamanı hatası verecek (hata ayıklamayı gereksizleştiriyor) 25 | // 26 | {} + []; // JS : 0, TS Error 27 | [] + {}; // JS : "[object Object]", TS Error 28 | {} + {}; // JS : NaN, TS Error 29 | "merhaba" - 1; // JS : NaN, TS Error 30 | 31 | function ekle(a,b) { 32 | return 33 | a + b; // JS : undefined, TS Error 'unreachable code detected' 34 | } 35 | ``` 36 | 37 | Esasen TypeScript JavaScript'i potansiyel hatalar için analiz eder. Sadece benzer işi yapıp, tür bilgisi olmayan diğerlerinden daha iyi bir iş çıkarıyor. 38 | 39 | ## Hala JavaScript öğrenmeniz gerekiyor 40 | 41 | Bunun anlamı TypeScript *JavaScript yazmanız* gerçeği hakkında oldukça faydalıdır. Yani gafil avlanmamanız için JavaScript ile ilgili hala farkına varmanız gereken bazı şeyler var. Gelin şimdi bunları tartışalım. -------------------------------------------------------------------------------- /docs/options/intro.md: -------------------------------------------------------------------------------- 1 | # Convenience vs. Soundness 2 | 3 | There are a few things that TypeScript prevents you from doing out of the box e.g using a variable that *isn't ever declared* (of course you can use a *declaration file* for external systems). 4 | 5 | That said, traditionally programming languages have a hard boundary between what is and isn't allowed by the type system. TypeScript is different in that it gives you control on where you put the slider. This is really to allow you to use the JavaScript you know and love with as much safety as **you** want. There are lot of compiler options to control exactly this slider so let's have a look. 6 | 7 | 8 | ### Boolean Options 9 | 10 | `compilerOptions` that are `boolean` can be specified as `compilerOptions` in `tsconfig.json`: 11 | 12 | ```json 13 | { 14 | "compilerOptions": { 15 | "someBooleanOption": true 16 | } 17 | } 18 | ``` 19 | 20 | or on the command line 21 | 22 | ```sh 23 | tsc --someBooleanOption 24 | ``` 25 | 26 | > All of these are `false` by default. 27 | 28 | Click [here](https://www.typescriptlang.org/docs/handbook/compiler-options.html) to see all compiler options. 29 | -------------------------------------------------------------------------------- /docs/options/noImplicitAny.md: -------------------------------------------------------------------------------- 1 | ## noImplicitAny 2 | 3 | There are some things that cannot be inferred or inferring them might result in errors that might be unexpected. A fine example is function arguments. If you don't annotate them its unclear what should and shouldn't be valid e.g. 4 | 5 | 6 | ```ts 7 | function log(someArg) { 8 | sendDataToServer(someArg); 9 | } 10 | 11 | // What arg is valid and what isn't? 12 | log(123); 13 | log('hello world'); 14 | ``` 15 | 16 | So if you don't annotate some function argument TypeScript assumes `any` and moves on. This essentially turns off type checking for such cases which is what a JavaScript dev would expect but can catch people that want high safety off guard. Hence there is an option `noImplicitAny` that when switched on will flag the cases where the type cannot be inferred e.g. 17 | 18 | 19 | ```ts 20 | function log(someArg) { // Error : someArg has an implicit `any` type 21 | sendDataToServer(someArg); 22 | } 23 | ``` 24 | 25 | of course you can then go ahead an annotate: 26 | 27 | ```ts 28 | function log(someArg: number) { 29 | sendDataToServer(someArg); 30 | } 31 | ``` 32 | 33 | And if you truly want *zero safety* you can mark it *explicitly* as `any`: 34 | 35 | ```ts 36 | function log(someArg: any) { 37 | sendDataToServer(someArg); 38 | } 39 | ``` 40 | -------------------------------------------------------------------------------- /docs/options/strictNullChecks.md: -------------------------------------------------------------------------------- 1 | ## `strictNullChecks` 2 | By default `null` and `undefined` are assignable to all types in TypeScript e.g. 3 | 4 | ```ts 5 | let foo: number = 123; 6 | foo = null; // Okay 7 | foo = undefined; // Okay 8 | ``` 9 | 10 | This is modelled after how a lot of people write JavaScript. However like all things TypeScript allows you to be *explicit* about what *can and cannot be* assigned a `null` or `undefined`. 11 | 12 | In strict null checking mode, `null` and `undefined` are different: 13 | 14 | ```ts 15 | let foo = undefined; 16 | foo = null; // NOT Okay 17 | ``` 18 | 19 | Let say we have a `Member` interface: 20 | 21 | ```ts 22 | interface Member { 23 | name: string, 24 | age?: number 25 | } 26 | ``` 27 | 28 | Not every member will provide their age, so the `age` is an optional property. It means the value of `age` will probably be `undefined`. 29 | 30 | `undefined` is the root of all evil. It always lead to runtime error. We are always easy to write some code that will probably throw `Error`: 31 | 32 | ```ts 33 | getMember() 34 | .then(member: Member => { 35 | const stringifyAge = member.age.toString() // probably throw Cannot read property 'toString' of undefined 36 | }) 37 | ``` 38 | 39 | But in strict null checking mode, it will throw an error at compile time: 40 | 41 | ```ts 42 | getMember() 43 | .then(member: Member => { 44 | const stringifyAge = member.age.toString() // Object is possibly 'undefined' 45 | }) 46 | ``` 47 | -------------------------------------------------------------------------------- /docs/project/compilation-context.md: -------------------------------------------------------------------------------- 1 | ## Derleme İçerigi (Compilation Context) 2 | Derleme içeriği temelde, TypeScript'in ayrıştırılacak ve analiz edilecek dosyaların gruplandırılması için neyin geçerli, neyin olmadığını belirlemek için basit bir terimdir. Hangi dosyalarla ilgili olduğu bilgisinin yanısıra, derleme içeriği *hangi derleyici seçenekleri*'nin kullanıldığı hakkında bilgi içerir. Bu mantıksal gruplamayı tanımlamanın en harika yolu `tsconfig.json` dosyası kullanmaktır (biz *project* terimini kullanmayı da seviyoruz). 3 | -------------------------------------------------------------------------------- /docs/project/declarationspaces.md: -------------------------------------------------------------------------------- 1 | ## Deklarasyon Alanları 2 | 3 | TypeScript'te iki deklarasyon alanı vardır: *variable (değişken)* deklarasyon alanı ve *type (tip)* deklarasyon alanı. Bu konseptler aşağıda incelenmiştir. 4 | 5 | ### Type (Tip) Deklarasyon Alanı 6 | Type (tip) deklarasyon alanı, tip belirteci olarak kullanılabilecek öğeleri içerir. Aşağıdakiler birkaç tip deklarasyona örnektir: 7 | 8 | ```ts 9 | class Foo { } 10 | interface Bar { } 11 | type Bas = {} 12 | ``` 13 | Bunun anlamı `Foo`, `Bar`, `Bas` vb. tip belirteci olarak kullanabilirsiniz. Örneğin: 14 | 15 | ```ts 16 | var foo: Foo; 17 | var bar: Bar; 18 | var bas: Bas; 19 | ``` 20 | 21 | Dikkat edin `interface Bar`'a sahip olsanız bile *onu değişken olarak kullanamazsınız*, çünkü o *variable (değişken) deklarasyon alanında* tanımlanıp aktarılamamış. Aşağıdaki örnekte gösterilmiştir: 22 | 23 | ```ts 24 | interface Bar {}; 25 | var bar = Bar; // ERROR: "cannot find name 'Bar'" 26 | ``` 27 | 28 | `cannot find name (isim bulunamıyor)` demesinin sebebi ise, `Bar` isminin *variable (değişken)* deklarasyon alanında *tanımlanmamış* olmasıdır. Bu bizi bir sonraki "Variable (Değişken) Deklarasyon Alanı" konusuna götürüyor. 29 | 30 | ### Variable (Değişken) Deklarasyon Alanı 31 | Variable (değişken) deklarasyon alanı, değişken belirteci olarak kullanılabilecek öğeleri içerir. `class Foo`'nun tip `Foo` olarak tanımlanıp *tip* deklarasyon alanına aktarılabildiğini gördük. Tahmin edin?, *değişken* `Foo` aynı zamanda *variable (değişken)* deklarasyon alanına aşağıda gösterildiği gibi tanımlanıp aktarıldı: 32 | 33 | ```ts 34 | class Foo { } 35 | var someVar = Foo; 36 | var someOtherVar = 123; 37 | ``` 38 | Bazen sınıfları değişkenler olarak aktarmak istediğimiz için bu harika. Şunu hatırlayın 39 | 40 | * *Sadece* *tip* deklarasyon alanındaki `interface (arayüz)` gibi şeyleri bir değişken olarak kullanamadık. 41 | 42 | `var` olarak tanımladığınız birşey benzer olarak, *sadece* *variable (değişken)* deklarasyon alanı içerisinde olabilir ve tip belirteci olarak kullanılamaz: 43 | 44 | ```ts 45 | var foo = 123; 46 | var bar: foo; // ERROR: "cannot find name 'foo'" 47 | ``` 48 | `cannot find name (isim bulunamıyor)` demesinin sebebi ise, `foo` isminin *type (tip)* deklarasyon alanında *tanımlanmamış* olmasıdır. 49 | -------------------------------------------------------------------------------- /docs/project/files.md: -------------------------------------------------------------------------------- 1 | ## Hangi dosyalar? 2 | 3 | Açık olarak ifade edebilmek için iki şekilde `files` kullanabilirsiniz: 4 | 5 | ```json 6 | { 7 | "files":[ 8 | "./some/file.ts" 9 | ] 10 | } 11 | ``` 12 | 13 | veya `include` ve `exclude` ile dosyaları belirtebilirsiniz. Örneğin, 14 | 15 | 16 | ```json 17 | { 18 | "include":[ 19 | "./folder" 20 | ], 21 | "exclude":[ 22 | "./folder/**/*.spec.ts", 23 | "./folder/someSubFolder" 24 | ] 25 | } 26 | ``` 27 | 28 | Birkaç not: 29 | 30 | * eğer `files` belirtildiyse diğer seçenekler yok sayılır 31 | * `**/*` (örnek kullanımı `somefolder/**/*`) bütün klasörler ve bazı dosyalar anlamına gelir (`.ts`/`.tsx` dosya uzantıları dahil olacaktır ve eğer `allowJs` true ise `.js`/`.jsx` uzantıları bile bu uzantılara dahil olacaktır) 32 | -------------------------------------------------------------------------------- /docs/project/globals.md: -------------------------------------------------------------------------------- 1 | # globals.d.ts 2 | 3 | We discussed *global* vs. *file* modules when covering [projects](./modules.md) and recommended using file based modules and not polluting the global namespace. 4 | 5 | Nevertheless it is convenient to have *some* files just with type declarations (for smaller projects preferably one called `globals.d.ts`) in the global namespace to make it easy to have some *types* just *magically* available for consumption in *all* your TypeScript code. For any code that is going to generate *JavaScript* we still recommend using *file modules*. 6 | 7 | `globals.d.ts` is great for adding extensions to `lib.d.ts`. 8 | -------------------------------------------------------------------------------- /docs/project/modules.md: -------------------------------------------------------------------------------- 1 | ## Modules 2 | 3 | ### Global Module 4 | 5 | By default when you start typing code in a new TypeScript file your code is in a *global* namespace. As a demo consider a file `foo.ts`: 6 | 7 | ```ts 8 | var foo = 123; 9 | ``` 10 | 11 | If you now create a *new* file `bar.ts` in the same project, you will be *allowed* by the TypeScript type system to use the variable `foo` as if it was available globally: 12 | 13 | ```ts 14 | var bar = foo; // allowed 15 | ``` 16 | Needless to say having a global namespace is dangerous as it opens your code up for naming conflicts. We recommend using file modules which are presented next. 17 | 18 | ### File Module 19 | Also called *external modules*. If you have an `import` or an `export` at the root level of a TypeScript file then it creates a *local* scope within that file. So if we were to change the previous `foo.ts` to the following (note the `export` usage): 20 | 21 | ```ts 22 | export var foo = 123; 23 | ``` 24 | 25 | We will no longer have `foo` in the global namespace. This can be demonstrated by creating a new file `bar.ts` as follows: 26 | 27 | ```ts 28 | var bar = foo; // ERROR: "cannot find name 'foo'" 29 | ``` 30 | 31 | If you want to use stuff from `foo.ts` in `bar.ts` *you need to explicitly import it*. This is shown in an updated `bar.ts` below: 32 | 33 | ```ts 34 | import {foo} from "./foo"; 35 | var bar = foo; // allowed 36 | ``` 37 | Using an `import` in `bar.ts` not only allows you to bring in stuff from other files, but also marks the file `foo.ts` as a *module* and therefore `foo.ts` doesn't pollute the global namespace either. 38 | 39 | What JavaScript is generated from a given TypeScript file that uses external modules is driven by the compiler flag called `module`. 40 | -------------------------------------------------------------------------------- /docs/project/namespaces.md: -------------------------------------------------------------------------------- 1 | ## Aduzayları (Namespaces) 2 | Aduzayları, JavaScript'te kullanılan yaygın bir kalıp için uygun sözdizimi sağlar: 3 | 4 | ```ts 5 | (function(something) { 6 | 7 | something.foo = 123; 8 | 9 | })(something || something = {}) 10 | ``` 11 | Basit olarak anlatmak gerekirse `something || something = {}` ifadesi, anonim fonksiyonun *varolan bir nesneye eklenti yapmasını* (`something ||` kısmı) veya *yeni bir obje yaratarak yaratılan bu yeni objeye eklenti yapılmasına* (`|| something = {}` kısmı) imkan tanır. 12 | Bunun anlamı şudur, bir çalıştırma sınırıyla ayrılmış iki farklı kod bloğuna sahip olabilirsiniz: 13 | 14 | 15 | ```ts 16 | (function(something) { 17 | 18 | something.foo = 123; 19 | 20 | })(something || something = {}) 21 | 22 | console.log(something); // {foo:123} 23 | 24 | (function(something) { 25 | 26 | something.bar = 456; 27 | 28 | })(something || something = {}) 29 | 30 | console.log(something); // {foo:123, bar:456} 31 | 32 | ``` 33 | Javascript'te bunun en yaygın kullanım amacı global(küresel) aduzayına bilgi sızmasını önlemektir. Dosya tabanlı modüller kullanıldığında bu konu hakkında endişe etmenize gerek olmamakla birlikte, bu kalıp fonksiyonlarınızı *mantıksal olarak gruplamak* için oldukça kullanışlıdır. Bu tip gruplamaları yapabilmeniz için TypeScript `namespace` anahtar kelimesini sunmaktadır. Ör: 34 | 35 | ```ts 36 | namespace Utility { 37 | export function log(msg) { 38 | console.log(msg); 39 | } 40 | export function error(msg) { 41 | console.error(msg); 42 | } 43 | } 44 | 45 | // usage 46 | Utility.log('Call me'); 47 | Utility.error('maybe!'); 48 | ``` 49 | `namespace` anahtar kelimesi ilk bölümde gördüğümüz JavaScript kodunun aynısını üretmektedir. 50 | 51 | ```ts 52 | (function (Utility) { 53 | 54 | // Add stuff to Utility 55 | 56 | })(Utility || (Utility = {})); 57 | ``` 58 | Bir diğer nokta ise, aduzaylarının iç içe geçebiliyor olmalarıdır, bu sayede `namespace Utility.Messaging` gibi bir ifadeyle `Messaging` aduzayını `Utility` aduzayının içerisinde tanımlamak mümkün olmaktadır. 59 | 60 | Örnek proje oluştururken veya eski JavaScript kodunu port ederken harici modül ve `namespace` kullanılması tavsiye edilmektedir. 61 | -------------------------------------------------------------------------------- /docs/project/project.md: -------------------------------------------------------------------------------- 1 | # Proje 2 | 3 | TypeScript kullanarak başarılı bir proje oluşturmak için,proje organizasyonunun daha iyi olmasını sağlayan Typescript özelliklerini iyi anlamak gerekir. Bu bölümde, "derleme içeriği(compilation context)", deklarasyon alanları ve modülleri ele alacağız. 4 | -------------------------------------------------------------------------------- /docs/project/tsconfig.md: -------------------------------------------------------------------------------- 1 | ### Basic 2 | It is extremely easy to get started with tsconfig.json as the basic file you need is: 3 | ```json 4 | {} 5 | ``` 6 | i.e. an empty JSON file at the *root* of your project. This way TypeScript will include *all* the `.ts` files in this directory (and sub directories) as a part of the compilation context. It will also select a few sane default compiler options. 7 | 8 | ### compilerOptions 9 | You can customize the compiler options using `compilerOptions`. 10 | 11 | ```json 12 | { 13 | "compilerOptions": { 14 | "target": "es5", 15 | "module": "commonjs", 16 | "declaration": false, 17 | "noImplicitAny": false, 18 | "removeComments": true, 19 | "noLib": false 20 | } 21 | } 22 | ``` 23 | 24 | These (and more) compiler options will be discussed later. 25 | 26 | ### TypeScript compiler 27 | Good IDEs come with built in support for on the fly `ts` to `js` compilation. If however you want to run the TypeScript compiler manually from the command line when using `tsconfig.json` you can do it in a few ways. 28 | * Just run `tsc` and it will look for `tsconfig.json` in the current as well as all parent folders till it finds it. 29 | * Run `tsc -p ./path-to-project-directory`. Of course the path can be a complete or relative to the current directory. 30 | 31 | You can even start the TypeScript compiler in *watch* mode using `tsc -w` and it will watch your TypeScript project files for changes. 32 | -------------------------------------------------------------------------------- /docs/quick/nodejs.md: -------------------------------------------------------------------------------- 1 | # TypeScript with NodeJS 2 | TypeScript has had *first class* support for NodeJS since inception. Here's how to setup a quick NodeJS project: 3 | 4 | > Note: many of these steps are actually just common practice nodejs setup steps 5 | 6 | 1. Setup a nodejs project `package.json`. Quick one : `npm init -y` 7 | 1. Add TypeScript (`npm install typescript --save-dev`) 8 | 1. Add `node.d.ts` (`npm install @types/node --save-dev`) 9 | 1. Init a `tsconfig.json` for TypeScript options (`node ./node_modules/typescript/lib/tsc --init`) 10 | 11 | That's it! Fire up your IDE (e.g. `alm -o`) and play around. Now you can use all the built in node modules (e.g. `import fs = require('fs')`) with all the safety and developer ergonomics of TypeScript! 12 | 13 | ## Bonus: Live compile + run 14 | * Add `ts-node` which we will use for live compile + run in node (`npm install ts-node --save-dev`) 15 | * Add `nodemon` which will invoke `ts-node` whenever a file is changed (`npm install nodemon --save-dev`) 16 | 17 | Now just add a `script` target to your `package.json` based on your application entry e.g. assuming its `index.ts`: 18 | 19 | ```json 20 | "scripts": { 21 | "start": "npm run build:live", 22 | "build:live": "nodemon --exec ./node_modules/.bin/ts-node -- ./index.ts" 23 | }, 24 | ``` 25 | So you can now run `npm start` and as you edit `index.ts`: 26 | 27 | * nodemon rereuns its command (ts-node) 28 | * ts-node transpiles automatically picking up tsconfig.json and the installed typescript version 29 | * ts-node runs the output javascript through node. 30 | 31 | ## Creating TypeScript node modules 32 | 33 | You can even use other node modules written in TypeScript. As a module author, one real thing you should do: 34 | 35 | * you might want to have a `typings` field (e.g. `src/index`) in your `package.json` similar to the `main` field to point to the default TypeScript definition export. For an example look at [`package.json` for csx](https://github.com/typestyle/csx/blob/master/package.json). 36 | 37 | 38 | Example package: `npm install csx` [for csx](https://www.npmjs.com/package/csx), usage: `import csx = require('csx')`. 39 | 40 | 41 | ## Bonus points 42 | 43 | Such NPM modules work just fine with browserify (using tsify) or webpack (using ts-loader). 44 | -------------------------------------------------------------------------------- /docs/rest-parameters.md: -------------------------------------------------------------------------------- 1 | ### Rest Parametreleri 2 | Rest parametreleri, belirsiz sayıda argümanı bir dizi olarak alan fonksiyonlar oluşturabilmenize olanak sağlar. Tanımlaması ise, fonksiyonun son argümanının `...argumanIsmi` olarak ifade edilmesi ile gerçekleştirilir. Aşağıdaki örneği inceleyiniz. 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 parametreleri herhangi bir fonksiyonda kullanılabilir `function`/`()=>`/`class member`. 13 | -------------------------------------------------------------------------------- /docs/spread-operator.md: -------------------------------------------------------------------------------- 1 | ### Spread (Yayma) Operatörü 2 | Spread (Yayma) operatörünün ana hedefi bir dizinin elemanlarını *yaymaktır*. Bu operatörü açıklamak için örnekleri kullanacağız. 3 | 4 | #### Apply 5 | Yayma işleminin en yaygın kullanımlarından biri, dizinin elemanlarını bir fonksiyonun argümanları olarak kullanmaktır. Önceki sürümlerde bu işlemi yapmak için `Function.prototype.apply` ifadesini kullanmanız gerekmekteydi. 6 | 7 | ```ts 8 | function foo(x, y, z) { } 9 | var args = [0, 1, 2]; 10 | foo.apply(null, args); 11 | ``` 12 | 13 | Şimdi ise bu işlemi yapmak için gereken tek şey, aşağıdaki örnekte de görüleceği üzere, fonksiyon argümanlarınızın önüne `...` eklemektir. 14 | 15 | ```ts 16 | function foo(x, y, z) { } 17 | var args = [0, 1, 2]; 18 | foo(...args); 19 | ``` 20 | 21 | Yukarıdaki örnekte `args` dizisini fonksiyon argümanlarına dönüşecek şekilde yayıyoruz. 22 | 23 | #### Parçalama (Sökme) 24 | Bu konunun bir örneğini *destructuring* bölümünde görmüştük. 25 | 26 | ```ts 27 | var [x, y, ...remaining] = [1, 2, 3, 4]; 28 | console.log(x, y, remaining); // 1, 2, [3,4] 29 | ``` 30 | Bu örnekteki amaç, diziyi parçalarken dizide kalan eşleşmemiş elemanları kolay bir şekilde yakalayarak bir değişkene atamaktır. 31 | 32 | #### Dizi Atama (Birleştirme) 33 | Yayma operatörü, bir dizinin *yayılmış (genişletilmiş) versiyonunu* kolaylıkla başka bir dizinin içerisine yerleştirmenize olanak sağlar. Aşağıda bunun bir örneğini görebilirsiniz: 34 | 35 | ```ts 36 | var list = [1, 2]; 37 | list = [...list, 3, 4]; 38 | console.log(list); // [1,2,3,4] 39 | ``` 40 | 41 | #### Özet 42 | `apply` fonksiyonu JavaScript ile çalışırken kaçınılmaz olarak kullanacağınız bir ifadedir, bu sebeple `apply` fonksiyonunun ilk argümanı olan `this` yerine uygunsuz ve neredeyse çirkin denilebilecek bir sözdizimine yol açan `null` kullanmak yerine daha düzgün bir sözdizimi getiren *spread (yayma) operatörü* kullanmayı tercih edebilirsiniz. 43 | Bununla birlikte *spread (yayma) operatörü*, kısmı diziler üzerinden yapılan parçalama ve birleştirme işlemleri için çok daha zarif bir sözdizimi sunmaktadır. 44 | 45 | [](https://github.com/Microsoft/TypeScript/pull/1931) 46 | -------------------------------------------------------------------------------- /docs/staging/async-await.md: -------------------------------------------------------------------------------- 1 | ### Async - Await 2 | -------------------------------------------------------------------------------- /docs/staging/generators.md: -------------------------------------------------------------------------------- 1 | ### Generators 2 | Also called `function *`, generators allow you to create functions whose execution can be paused and then later resumed maintaining the state between pause-resume transitions. The value returned from a generator is called an `iterator` and can be used to control this `pause-resume` transition. 3 | 4 | Here is a simple example of a generator function that generates an *infinite* list of whole numbers. 5 | 6 | ```ts 7 | function* wholeNumbers() { 8 | var current = 0; 9 | while(true) { 10 | yield current++; 11 | } 12 | } 13 | ``` 14 | 15 | The `yield` contextual keyword is used to return control from a generator (effectively pausing function execution) along with an optional value (here `current`). You can get access to this value using the `iterator`'s `.next()` member function, this is shown below: 16 | 17 | ```ts 18 | function* wholeNumbers() { 19 | var current = 0; 20 | while(true) { 21 | yield current++; 22 | } 23 | } 24 | var iterator = wholeNumbers(); 25 | console.log(iterator.next()); // 0 26 | console.log(iterator.next()); // 1 27 | console.log(iterator.next()); // 2 28 | // so on till infinity.... 29 | ``` 30 | 31 | Now that you have seen `function*`, `yield` and `.next()` we can dig deeper. 32 | 33 | #### Catching Errors 34 | Any errors thrown (intentially using `throw` or unintentionally due to error) from the generator can be caught using `try/catch` just like normal function executions. This is demonstrated below: 35 | 36 | ```ts 37 | function* wholeNumbers() { 38 | var current = 0; 39 | while(true) { 40 | if (current === 3) 41 | throw new Error('3 is the magic number'); 42 | else 43 | yield current++; 44 | } 45 | } 46 | var iterator = wholeNumbers(); 47 | console.log(iterator.next()); // 0 48 | console.log(iterator.next()); // 1 49 | console.log(iterator.next()); // 2 50 | try { 51 | console.log(iterator.next()); // Will throw an error 52 | } 53 | catch(ex) { 54 | console.log(ex.message); // 3 is the magic number 55 | } 56 | ``` 57 | 58 | #### Controlling function execution externally 59 | The iterator returned from the generator function can be used to control the state *inside* the generator function as well. 60 | 61 | // TODO: example 62 | -------------------------------------------------------------------------------- /docs/styleguide/sample.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var formatting; 3 | (function (formatting) { 4 | var FooVar; 5 | function BarFunc() { } 6 | })(formatting || (formatting = {})); 7 | var asdfasdf; 8 | (function (asdfasdf) { 9 | var Foo = (function () { 10 | function Foo() { 11 | } 12 | Foo.prototype.baz = function () { }; 13 | return Foo; 14 | }()); 15 | })(asdfasdf || (asdfasdf = {})); 16 | -------------------------------------------------------------------------------- /docs/styleguide/sample.ts: -------------------------------------------------------------------------------- 1 | export var test; 2 | 3 | namespace formatting { 4 | var FooVar; 5 | function BarFunc() { } 6 | } 7 | 8 | namespace asdfasdf { 9 | class Foo { 10 | bar: number; 11 | baz() { } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /docs/styleguide/tsconfig.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /docs/tips/bind.md: -------------------------------------------------------------------------------- 1 | ## Bind is Harmful 2 | 3 | This is the definition of `bind` in `lib.d.ts`: 4 | 5 | ```ts 6 | bind(thisArg: any, ...argArray: any[]): any; 7 | ``` 8 | 9 | As you can see it returns **any**! That means that calling `bind` on a function will cause you to completely lose any type safety of the original function signature. 10 | 11 | For example the following compiles: 12 | 13 | ```ts 14 | function twoParams(a:number,b:number) { 15 | return a + b; 16 | } 17 | let curryOne = twoParams.bind(null,123); 18 | curryOne(456); // Okay but is not type checked! 19 | curryOne('456'); // Allowed because it wasn't type checked! 20 | ``` 21 | 22 | A better way to write it would be with a simple [arrow function](../arrow-functions.md) with an explicit type annotation: 23 | ```ts 24 | function twoParams(a:number,b:number) { 25 | return a + b; 26 | } 27 | let curryOne = (x:number)=>twoParams(123,x); 28 | curryOne(456); // Okay and type checked! 29 | curryOne('456'); // Error! 30 | ``` 31 | 32 | But if you expect a curried function [there is a better pattern for that](./currying.md). 33 | 34 | ### Class Members 35 | Another common use is to use `bind` to ensure the correct value of `this` when passing around class functions. Don't do that! 36 | 37 | The following demonstrates the fact that you lose parameter type safety if you use `bind`: 38 | 39 | ```ts 40 | class Adder { 41 | constructor(public a: string) { } 42 | 43 | add(b: string): string { 44 | return this.a + b; 45 | } 46 | } 47 | 48 | function useAdd(add: (x: number) => number) { 49 | return add(456); 50 | } 51 | 52 | let adder = new Adder('mary had a little 🐑'); 53 | useAdd(adder.add.bind(adder)); // No compile error! 54 | useAdd((x) => adder.add(x)); // Error: number is not assignable to string 55 | ``` 56 | 57 | If you have a class member function that you **expect** to pass around, [use an arrow function in the first place](../arrow-functions.md) e.g one would write the same `Adder` class as: 58 | 59 | ```ts 60 | class Adder { 61 | constructor(public a: string) { } 62 | 63 | // This function is now safe to pass around 64 | add = (b: string): string => { 65 | return this.a + b; 66 | } 67 | } 68 | ``` 69 | -------------------------------------------------------------------------------- /docs/tips/build-toggles.md: -------------------------------------------------------------------------------- 1 | ## Build Toggles 2 | 3 | It is common to switch in JavaScript projects based on where they are being run. You can do this quite easily with webpack as its supports *dead code elimination* based on environment variables. 4 | 5 | Add different targets in your `package.json` `scripts`: 6 | 7 | ```json 8 | "build:test": "webpack -p --config ./src/webpack.config.js", 9 | "build:prod": "webpack -p --define process.env.NODE_ENV='\"production\"' --config ./src/webpack.config.js", 10 | ``` 11 | 12 | Of course I am assuming you have `npm install webpack --save-dev`. Now you can run `npm run build:test` etc. 13 | 14 | Using this variable is super easy as well: 15 | 16 | ```ts 17 | /** 18 | * This interface makes sure we don't miss adding a property to both `prod` and `test` 19 | */ 20 | interface Config { 21 | someItem: string; 22 | } 23 | 24 | /** 25 | * We only export a single thing. The config. 26 | */ 27 | export let config: Config; 28 | 29 | /** 30 | * `process.env.NODE_ENV` definition is driven from webpack 31 | * 32 | * The whole `else` block will be removed in the emitted JavaScript 33 | * for a production build 34 | */ 35 | if (process.env.NODE_ENV === 'production') { 36 | config = { 37 | someItem: 'prod' 38 | } 39 | console.log('Running in prod'); 40 | } else { 41 | config = { 42 | someItem: 'test' 43 | } 44 | console.log('Running in test'); 45 | } 46 | ``` 47 | 48 | > We use `process.env.NODE_ENV` just because it is conventional in a lot of JavaScript libraries themselves e.g. `React`. 49 | -------------------------------------------------------------------------------- /docs/tips/classesAreUseful.md: -------------------------------------------------------------------------------- 1 | ## Classes Are Useful 2 | 3 | It is very common to have the following structure: 4 | 5 | ```ts 6 | function foo() { 7 | let someProperty; 8 | 9 | // Some other initialization code 10 | 11 | function someMethod() { 12 | // Do some stuff with `someProperty` 13 | // And potentially other things 14 | } 15 | // Maybe some other methods 16 | 17 | return { 18 | someMethod, 19 | // Maybe some other methods 20 | }; 21 | } 22 | ``` 23 | 24 | This is known as the *revealing module pattern* and quite common in JavaScript (taking advantage of JavaScript closure). 25 | 26 | If you use [*file modules* (which you really should as global scope is bad)](../project/modules.md) then *your file is effectively the same*. However there are too many cases where people will write code like the following: 27 | 28 | ```ts 29 | let someProperty; 30 | 31 | function foo() { 32 | // Some initialization code 33 | } 34 | foo(); // some initialization code 35 | 36 | someProperty = 123; // some more initialization 37 | 38 | // Some utility function not exported 39 | 40 | // later 41 | export function someMethod() { 42 | 43 | } 44 | ``` 45 | 46 | Even though I am not a big fan of inheritance *I do find that letting people use classes helps them organize their code better*. The same developer would intuitively write the following: 47 | 48 | ```ts 49 | class Foo { 50 | public someProperty; 51 | 52 | constructor() { 53 | // some initialization 54 | } 55 | 56 | public someMethod() { 57 | // some code 58 | } 59 | 60 | private someUtility() { 61 | // some code 62 | } 63 | } 64 | 65 | export = new Foo(); 66 | ``` 67 | 68 | And its not just developers, creating dev tools that provide great visualizations over classes are much more common, and there is one less pattern your team needs to understand and maintain. 69 | 70 | > PS: There is nothing wrong in my opinion with *shallow* class hierarchies if they provide significant reuse and reduction in boiler plate. 71 | -------------------------------------------------------------------------------- /docs/tips/currying.md: -------------------------------------------------------------------------------- 1 | ## Currying 2 | 3 | Just use a chain of fat arrow functions: 4 | 5 | ```ts 6 | // A curried function 7 | let add = (x: number) => (y: number) => x + y; 8 | 9 | // Simple usage 10 | add(123)(456); 11 | 12 | // partially applied 13 | let add123 = add(123); 14 | 15 | // fully apply the function 16 | add123(456); 17 | ``` 18 | -------------------------------------------------------------------------------- /docs/tips/defaultIsBad.md: -------------------------------------------------------------------------------- 1 | ## `export default` can lead to problems 2 | 3 | Let's go with an example. Consider you have a file `foo.ts` with the following contents: 4 | 5 | ```ts 6 | class Foo { 7 | } 8 | export default Foo; 9 | ``` 10 | 11 | You would import it (in `bar.ts`) using ES6 syntax as follows: 12 | 13 | ```ts 14 | import Foo from "./foo"; 15 | ``` 16 | 17 | There are a few maintainability concerns here: 18 | * If you refactor `Foo` in `foo.ts` it will not rename it in `bar.ts` 19 | * If you end up needing to export more stuff from `foo.ts` (which is what many of your files will have) then you have to juggle the import syntax. 20 | 21 | For this reason I recommend simple exports + destructured import. E.g. `foo.ts`: 22 | 23 | ```ts 24 | export class Foo { 25 | } 26 | ``` 27 | And then: 28 | 29 | ```ts 30 | import {Foo} from "./foo"; 31 | ``` 32 | 33 | 34 | > **Bonus points**: You even get autocomplete at this cursor location 35 | 36 | ```ts 37 | import {/*here*/} from "./foo"; 38 | ``` 39 | 40 | > **Bonus points**: Better commonJs experience 41 | 42 | Also its makes for a horrible experience for commonjs users who have to `const {default} = require('module/foo');` instead of `const {foo} = require('module/foo')` 43 | -------------------------------------------------------------------------------- /docs/tips/functionParameters.md: -------------------------------------------------------------------------------- 1 | # Function Parameters 2 | 3 | If you have a function that takes too many parameters, or parameters of the same type, then you might want to consider changing the function to take an object instead. 4 | 5 | Consider the following function: 6 | 7 | ```ts 8 | function foo(flagA: boolean, flagB: boolean) { 9 | // your awesome function body 10 | } 11 | ``` 12 | 13 | With such a function definition it's quite easy to invoke it incorrectly e.g. `foo(flagB, flagA)` and you would get no help from the compiler. 14 | 15 | Instead, convert the function to take an object: 16 | 17 | ```ts 18 | function foo(config: {flagA: boolean, flagB: boolean}) { 19 | const {flagA, flagB} = config; 20 | // your awesome function body 21 | } 22 | ``` 23 | Now the function calls will look like `foo({flagA, flagB})` which makes it much easier to spot mistakes and code review. 24 | 25 | > Note : If your function is simple enough, and you don't expect much churn, then feel free to ignore this advice 🌹. 26 | -------------------------------------------------------------------------------- /docs/tips/jquery.md: -------------------------------------------------------------------------------- 1 | ## JQuery Tips 2 | 3 | Note: you need to install the `jquery.d.ts` file for these tips 4 | 5 | ### Quickly define a new plugin 6 | 7 | Just create `jquery-foo.d.ts` with: 8 | 9 | ```ts 10 | interface JQuery { 11 | foo: any; 12 | } 13 | ``` 14 | 15 | And now you can use `$('something').foo({whateverYouWant:'hello jquery plugin'})` 16 | -------------------------------------------------------------------------------- /docs/tips/lazyObjectLiteralInitialization.md: -------------------------------------------------------------------------------- 1 | ## Lazy Object Literal Initialization 2 | 3 | Quite commonly in JavaScript code bases you would initialize and object literals in the following manner: 4 | 5 | ```ts 6 | let foo = {}; 7 | foo.bar = 123; 8 | foo.bas = "Hello World"; 9 | ``` 10 | 11 | As soon as you move the code to TypeScript you will start to get Errors like the following: 12 | 13 | ```ts 14 | let foo = {}; 15 | foo.bar = 123; // Error: Property 'bar' does not exist on type '{}' 16 | foo.bas = "Hello World"; // Error: Property 'bas' does not exist on type '{}' 17 | ``` 18 | 19 | This is because from the state `let foo = {}`, TypeScript *infers* the type of `foo` (left hand side of initializing assignment) to be the type of the right hand side `{}` (i.e. an object with no properties). So, it error if you try to assign to a property it doesn't know about. 20 | 21 | ### Ideal Fix 22 | 23 | The *proper* way to initialize an object in TypeScript is to do it in the assignment: 24 | 25 | ```ts 26 | let foo = { 27 | bar: 123, 28 | bas: "Hello World", 29 | }; 30 | ``` 31 | 32 | This is also great for code review and code maintainability purposes. 33 | 34 | ### Quick Fix 35 | 36 | If you have a large JavaScript code base that you are migrating to TypeScript the ideal fix might not be a viable solution for you. In that case you can carefully use a *type assertion* to silence the compiler: 37 | 38 | ```ts 39 | let foo = {} as any; 40 | foo.bar = 123; 41 | foo.bas = "Hello World"; 42 | ``` 43 | 44 | ### Middle Ground 45 | 46 | Of course using the `any` assertion can be very bad as it sort of defeats the safety of TypeScript. The middle ground fix is to create an `interface` to ensure 47 | 48 | * Good Docs 49 | * Safe assignment 50 | 51 | This is shown below: 52 | 53 | ```ts 54 | interface Foo { 55 | bar: number 56 | bas: string 57 | } 58 | 59 | let foo = {} as Foo; 60 | foo.bar = 123; 61 | foo.bas = "Hello World"; 62 | ``` 63 | 64 | Here is a quick example that shows the fact that using the interface can save you: 65 | 66 | ```ts 67 | interface Foo { 68 | bar: number 69 | bas: string 70 | } 71 | 72 | let foo = {} as Foo; 73 | foo.bar = 123; 74 | foo.bas = "Hello World"; 75 | 76 | // later in the codebase: 77 | foo.bar = 'Hello Stranger'; // Error: You probably misspelled `bas` as `bar`, cannot assign string to number 78 | } 79 | ``` 80 | -------------------------------------------------------------------------------- /docs/tips/main.md: -------------------------------------------------------------------------------- 1 | # TIPs 2 | In this section we present a number of tips that we have collected over the course of using TypeScript in the real world. 3 | -------------------------------------------------------------------------------- /docs/tips/mixins.md: -------------------------------------------------------------------------------- 1 | # Mixins 2 | -------------------------------------------------------------------------------- /docs/tips/propertySetters.md: -------------------------------------------------------------------------------- 1 | ## Limit usage of property setters 2 | 3 | Prefer explicit set/get functions (e.g. `setBar` and `getBar` functions) over setters/getters. 4 | 5 | Consider the following code: 6 | 7 | ```ts 8 | foo.bar = { 9 | a: 123, 10 | b: 456 11 | }; 12 | ``` 13 | 14 | In the presence of setter/getters: 15 | 16 | ```ts 17 | class Foo { 18 | a: number; 19 | b: number; 20 | set bar(value:{a:number,b:number}) { 21 | this.a = value.a; 22 | this.b = value.b; 23 | } 24 | } 25 | let foo = new Foo(); 26 | ``` 27 | 28 | This is not a *good* use of property setters. The person reading the first code sample has no context about all the things that will change. Where as someone calling `foo.setBar(value)` might have an idea that something might change on `foo`. 29 | 30 | > Bonus points: Find references works better if you have different functions. In TypeScript tools if you find references for a getter or a setter you get *both* whereas with explicit function calls you only get references to the relevant function. 31 | -------------------------------------------------------------------------------- /docs/tips/quickObjectReturn.md: -------------------------------------------------------------------------------- 1 | ## Return an object literal 2 | 3 | Sometimes you need a function that just returns a simple object literal. However, something like 4 | 5 | ```ts 6 | var foo = () => { 7 | bar: 123 8 | }; 9 | ``` 10 | is a parsed as a *block* containing a *JavaScript Label* by JavaScript runtimes (cause of the JavaScript specification). If that doesn't make sense, don't worry, as you get a nice compiler error from TypeScript saying "unused label" anyways. You can fix it by surrounding the object literal with `()`: 11 | 12 | ```ts 13 | var foo = () => ({ 14 | bar: 123 15 | }); 16 | ``` 17 | -------------------------------------------------------------------------------- /docs/tips/singleton.md: -------------------------------------------------------------------------------- 1 | # Singleton Pattern 2 | 3 | The conventional singleton pattern is really something that is used to overcome the fact that all code must be in a `class`. 4 | 5 | ```ts 6 | class Singleton { 7 | private static instance: Singleton; 8 | private constructor() { 9 | // do something construct... 10 | } 11 | static getInstance() { 12 | if (!Singleton.instance) { 13 | Singleton.instance = new Singleton(); 14 | // ... any one time initialization goes here ... 15 | } 16 | return Singleton.instance; 17 | } 18 | someMethod() { } 19 | } 20 | 21 | let something = new Singleton() // Error: constructor of 'Singleton' is private. 22 | 23 | let instance = Singleton.getInstance() // do something with the instance... 24 | ``` 25 | 26 | However if you don't want lazy initialization you can instead just use a `namespace`: 27 | 28 | ```ts 29 | namespace Singleton { 30 | // ... any one time initialization goes here ... 31 | export function someMethod() { } 32 | } 33 | // Usage 34 | Singleton.someMethod(); 35 | ``` 36 | 37 | > Warning : Singleton is just a fancy name for [global](http://stackoverflow.com/a/142450/390330) 38 | 39 | For most projects `namespace` can additionally be replaced by a *module*. 40 | 41 | ```ts 42 | // someFile.ts 43 | // ... any one time initialization goes here ... 44 | export function someMethod() { } 45 | 46 | // Usage 47 | import {someMethod} from "./someFile"; 48 | ``` 49 | 50 | 51 | -------------------------------------------------------------------------------- /docs/tips/statefulFunctions.md: -------------------------------------------------------------------------------- 1 | ## Stateful Functions 2 | A common feature in other programming languages is usage of the `static` keyword to increase the *lifetime* (not *scope*) of a function variable to live beyond function invocations. Here is a `C` sample that achieves this: 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 | Since JavaScript (or TypeScript) doesn't have function statics you can achieve the same thing using various abstractions that wrap over a local variable e.g. using a `class` : 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++ developers also try and achieve this using a pattern they call `functor` (a class that overrides the operator `()`). 34 | -------------------------------------------------------------------------------- /docs/tips/staticConstructor.md: -------------------------------------------------------------------------------- 1 | # Static Constructors in TypeScript 2 | 3 | TypeScript `class` (like JavaScript `class`) cannot have a static constructor. However you can get the same effect quite easily by just calling it yourself: 4 | 5 | ```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 | Sometimes you need a collection of strings collected under a common key. TypeScript does have enum support but [it is `number` based](../enums.md). However TypeScript does have [string literal types and you can use those as string based enums quite easily by combining with union types](../types/literal-types.md). 4 | -------------------------------------------------------------------------------- /docs/tips/truthy.md: -------------------------------------------------------------------------------- 1 | ## Truthy 2 | 3 | JavaScript has a concept of `truthy` i.e. things that evaluate like `true` would in certain positions (e.g. `if` conditions and the boolean `&&` `||` operators). The following things are truthy in JavaScript. An example is any number other than `0` e.g. 4 | 5 | ```ts 6 | if (123) { // Will be treated like `true` 7 | console.log('Any number other than 0 is truthy'); 8 | } 9 | ``` 10 | 11 | Something that isn't truthy is called `falsy`. 12 | 13 | Here's a handy table for your reference. 14 | 15 | | Variable Type | When it is *falsy* | When it is *truthy* | 16 | |-----------------|--------------------------|--------------------------| 17 | | `boolean` | `false` | `true` | 18 | | `string` | `''` (empty string) | any other string | 19 | | `number` | `0` `NaN` | any other number | 20 | | `null` | always | never | 21 | | `undefined` | always | never | 22 | | Any other Object including empty ones like `{}`,`[]` | never | always | 23 | 24 | 25 | ### Being explicit 26 | 27 | > The `!!` pattern 28 | 29 | Quite commonly it helps to be explicit that the intent is to treat the value as a `boolean` and convert it into a *true boolean* (one of `true`|`false`). You can easily convert values to a true boolean by prefixing it with `!!` e.g. `!!foo`. Its just `!` used *twice*. The first `!` converts the variable (in this case `foo`) to a boolean but inverts the logic (*truthy* -`!`> `false`, *falsy* -`!`> `true`). The second one toggles it again to match the nature of the original object (e.g. *truthy* -`!`> `false` -`!`> `true`). 30 | 31 | It is common to use this pattern in lots of places e.g. 32 | 33 | ```ts 34 | // Direct variables 35 | const hasName = !!name; 36 | 37 | // As members of objects 38 | const someObj = { 39 | hasName: !!name 40 | } 41 | 42 | // e.g. ReactJS 43 | {!!someName &&
{someName}
} 44 | ``` 45 | -------------------------------------------------------------------------------- /docs/tips/typeInstantiation.md: -------------------------------------------------------------------------------- 1 | ## Type Instantiation for Generics 2 | 3 | Say you have something that has a generic parameter e.g. a class `Foo`: 4 | 5 | ```ts 6 | class Foo{ 7 | foo: T; 8 | } 9 | ``` 10 | 11 | You want to create a specialized version for it for a particular type. The pattern is to copy the item into a new variable and give it the type annotation with the generics replaced with concrete types. E.g if you want a class `Foo`: 12 | 13 | ```ts 14 | class Foo{ 15 | foo: T; 16 | } 17 | let FooNumber = Foo as { new ():Foo }; // ref 1 18 | ``` 19 | In `ref 1` you are saying that `FooNumber` is the same as `Foo` but just treat it as something that when called with the `new` operator gives an instance of `Foo`. 20 | 21 | ### Inheritance 22 | The Type assertion pattern is unsafe in that it trusts you to do the right thing. A common pattern in other languages *for classes* is to just use inheritance : 23 | 24 | ```ts 25 | class FooNumber extends Foo{} 26 | ``` 27 | 28 | One word of caution here: if you use decorators on the base class then the inherited class might not have the same behavior as the base class (it is no longer wrapped by the decorator). 29 | 30 | Of course if you are not specializing classes you still have to come up with a coercion / assertion pattern that works and hence we showed the general assertion pattern first, e.g.: 31 | 32 | ```ts 33 | function id(x: T) { return x; } 34 | const idNum = id as {(x:number):number}; 35 | ``` 36 | 37 | > Inspired by this [stackoverflow question](http://stackoverflow.com/a/34864705/390330) 38 | -------------------------------------------------------------------------------- /docs/types/@types.md: -------------------------------------------------------------------------------- 1 | # `@types` 2 | 3 | [Definitely Typed](https://github.com/DefinitelyTyped/DefinitelyTyped) is definitely one of TypeScript's greatest strengths. The community has effectively gone ahead and **documented** the nature of nearly 90% of the top JavaScript projects out there. 4 | 5 | This means that you can use these projects in a very interactive an exploratory manner, no need to have the docs open in a seperate window and making sure you don't make a typo. 6 | 7 | ## Using `@types` 8 | 9 | Installation is fairly simple as it just works on top of `npm`. So as an example you can install type definitions for `jquery` simply as : 10 | 11 | ``` 12 | npm install @types/jquery --save-dev 13 | ``` 14 | 15 | `@types` supports both *global* and *module* type definitions. 16 | 17 | 18 | ### Global `@types` 19 | 20 | By default any definitions that support global consumption are included automatically. e.g. for `jquery` you should be able to just start using `$` *globally* in your project. 21 | 22 | However for *libraries* (like `jquery`) I generally recommend using *modules*: 23 | 24 | ### Module `@types` 25 | 26 | After installation, no special configuration is required really. You just use it like a module e.g. 27 | 28 | ``` 29 | import * as $ from "jquery"; 30 | 31 | // Use $ at will in this module :) 32 | ``` 33 | 34 | ## Controlling Globals 35 | 36 | As can be seen having a definition that supports global leak in automatically can be a problem for some team so you can chose to *explicitly* only bring in the types that make sense using the `tsconfig.json` `compilerOptions.types` e.g. 37 | 38 | ``` 39 | { 40 | "compilerOptions": { 41 | "types" : [ 42 | "jquery" 43 | ] 44 | } 45 | } 46 | ``` 47 | 48 | The above shows a sample where only `jquery` will be allowed to be used. Even if the person installs another definition like `npm install @types/node` it's globals (e.g. [`process`](https://nodejs.org/api/process.html)) will not leak into your code until you add them to the `tsconfig.json` types option. 49 | -------------------------------------------------------------------------------- /docs/types/ambient/d.ts.md: -------------------------------------------------------------------------------- 1 | ### Declaration file 2 | You can tell TypeScript that you are trying to describe code that exists elsewhere (e.g. written in JavaScript/CoffeeScript/The runtime environment like the browser or nodejs) using the `declare` keyword. As a quick example: 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 | You have the option of putting these declarations in a `.ts` file or in a `.d.ts` file. We highly recommend that in your real world projects you use a separate `.d.ts` (start with one called something like `globals.d.ts` or `vendor.d.ts`). 14 | 15 | If a file has the extension `.d.ts` then each root level definition must have the `declare` keyword prefixed to it. This helps make it clear to the author that there will be *no code emitted by TypeScript*. The author needs to ensure that the declared item will exist at runtime. 16 | 17 | > * Ambient declarations is a promise that you are making with the compiler. If these do not exist at runtime and you try to use them, things will break without warning. 18 | * Ambient declarations are like docs. If the source changes the docs need to be kept updated. So you might have new behaviours that work at runtime but no one's updated the ambient declaration and hence you get compiler errors. 19 | -------------------------------------------------------------------------------- /docs/types/ambient/intro.md: -------------------------------------------------------------------------------- 1 | ## Ambient Declarations 2 | 3 | As we mentioned in [why TypeScript](../../why-typescript.md): 4 | 5 | > A major design goal of TypeScript was to make it possible for you to safely and easily use existing JavaScript libraries in TypeScript. TypeScript does this by means of *declaration* 6 | 7 | Ambient declarations allow you to *safely use existing popular JavaScript libraries* and *incrementally migrate your JavaScript/CoffeeScript/Others-Compile-To-Js-Language project to TypeScript*. 8 | 9 | Studying patterns in ambient declarations for *third party JavaScript code* is good practice for annotating *your* TypeScript code base as well. This is why we present it so early on. 10 | -------------------------------------------------------------------------------- /docs/types/ambient/variables.md: -------------------------------------------------------------------------------- 1 | ### Variables 2 | For example to tell TypeScript about the [`process` variable](https://nodejs.org/api/process.html) you *can* do: 3 | 4 | ```ts 5 | declare var process:any; 6 | ``` 7 | 8 | > You don't *need* to do this for `process` as there is already a [community maintained `node.d.ts`](https://github.com/borisyankov/DefinitelyTyped/blob/master/node/node.d.ts) 9 | 10 | This allows you to use the `process` variable without TypeScript complaining: 11 | 12 | ```ts 13 | process.exit() 14 | ``` 15 | 16 | We recommend using an interface wherever possible e.g: 17 | 18 | ```ts 19 | interface Process { 20 | exit(code?:number):void; 21 | } 22 | declare var process: Process; 23 | ``` 24 | 25 | This allows other people to *extend* the nature of these global variables while still telling TypeScript about such modifications. E.g. consider the following case where we add an `exitWithLogging` function to process for our amusement: 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 | Let's look at interfaces in a bit more detail next. 38 | -------------------------------------------------------------------------------- /docs/types/literal-types.md: -------------------------------------------------------------------------------- 1 | ## String Literal Type 2 | 3 | You can use a string literal as a type. For example: 4 | 5 | ```ts 6 | let foo: 'Hello'; 7 | ``` 8 | Here we have created a variable called `foo` that *will only allow the literal value `'Hello'` to be assigned to it*. This is demonstrated below: 9 | 10 | ```ts 11 | let foo: 'Hello'; 12 | foo = 'Bar'; // Error: "Bar" is not assignable to type "Hello" 13 | ``` 14 | 15 | They are not very useful on their own but can be combined in a type union to create a powerful (and useful) abstraction e.g.: 16 | 17 | ```ts 18 | type CardinalDirection = 19 | "North" 20 | | "East" 21 | | "South" 22 | | "West"; 23 | 24 | function move(distance: number, direction: CardinalDirection) { 25 | // ... 26 | } 27 | 28 | move(1,"North"); // Okay 29 | move(1,"Nurth"); // Error! 30 | ``` 31 | 32 | ### Use cases 33 | Valid use cases for string literal types are: 34 | 35 | #### String based enums 36 | 37 | [TypeScript enums are number based](../enums.md). You can use string literals with union types to mock a string based enum as we did in the `CardinalDirection` example above. 38 | 39 | #### Modelling existing JavaScript APIs 40 | 41 | e.g. [CodeMirror editor has an option `readOnly`](https://codemirror.net/doc/manual.html#option_readOnly) that can either be a `boolean` or the literal string `"nocursor"` (effective valid values `true,false,"nocursor"`). It can be declared as: 42 | 43 | ```ts 44 | readOnly: boolean | 'nocursor'; 45 | ``` 46 | 47 | #### Discriminated Unions 48 | 49 | We will cover [this later in the book](./discriminated-unions.md). 50 | 51 | 52 | [](https://github.com/Microsoft/TypeScript/pull/5185) 53 | -------------------------------------------------------------------------------- /docs/types/never.md: -------------------------------------------------------------------------------- 1 | # Never 2 | 3 | > Never ever ever (joke) 4 | 5 | Programming language design does have a concept of *bottom* type that is a **natural** outcome as soon as you do *code flow analysis*. TypeScript does *code flow analysis* (😎) and so it needs to reliably represent stuff that might never happen. 6 | 7 | The `never` type is used in TypeScript to denote this *bottom* type. Cases when it occurs naturally: 8 | 9 | * A function never returns (e.g. if the function body has `while(true){}`) 10 | * A function always throws (e.g. in `function foo(){throw new Error('Not Implemented')}` the return type of `foo` is `never`) 11 | 12 | Of course you can use this annotation your self as well 13 | 14 | ```ts 15 | let foo: never; // Okay 16 | ``` 17 | 18 | However `never` *can only ever be assigned to another never*. e.g. 19 | 20 | ```ts 21 | let foo: never = 123; // Error: Type number is not assignable to never 22 | 23 | // Okay as the function's return type is `never` 24 | let bar: never = (() => { throw new Error('Throw my hands in the air like I just dont care') })(); 25 | ``` 26 | 27 | Great. Now let's just jump into its key use case :) 28 | 29 | # Use case: Exhaustive Checks 30 | 31 | You can call never functions in a never context 32 | 33 | ``` 34 | function foo(x: string | number): boolean { 35 | if (typeof x === "string") { 36 | return true; 37 | } else if (typeof x === "number") { 38 | return false; 39 | } 40 | 41 | // Without a never type we would error : 42 | // - Not all code paths return a value (strict null checks) 43 | // - Or Unreachable code detected 44 | // But because typescript understands that `fail` function returns `never` 45 | // It can allow you to call it as you might be using it for runtime safety / exhaustive checks. 46 | fail("Unexhaustive!"); 47 | } 48 | 49 | function fail(message: string) { throw new Error(message); } 50 | ``` 51 | 52 | And because `never` is only assignable to another `never` you can use it for *compile time* exhaustive checks as well. This is covered in the [*discriminated union* section](./discriminated-unions.md). 53 | 54 | # Confusion with `void` 55 | 56 | As soon as someone tells you that `never` is returned when a function never exits gracefully you intutively want to think of it as the same as `void` However `void` is a Unit. `never` is a falsum. 57 | 58 | A function that *returns* nothing returns a Unit `void`. However a function *that never returns* (or always throws) returns `never`. `void` is something that can be assigned (without `strictNullChecking`) but `never` can `never` be assigned to anything other than `never`. 59 | 60 | 65 | -------------------------------------------------------------------------------- /footer.md: -------------------------------------------------------------------------------- 1 | [![fork me](/images/github.png) Fork me on github](https://github.com/basarat/typescript-book/) 2 | -------------------------------------------------------------------------------- /images/atomts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeFiction/typescript-book/a5b2250c7332fe10b04a281e3aad19d75bf0aea4/images/atomts.png -------------------------------------------------------------------------------- /images/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeFiction/typescript-book/a5b2250c7332fe10b04a281e3aad19d75bf0aea4/images/github.png -------------------------------------------------------------------------------- /images/promise states and fates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeFiction/typescript-book/a5b2250c7332fe10b04a281e3aad19d75bf0aea4/images/promise states and fates.png -------------------------------------------------------------------------------- /images/promise states and fates.vsd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeFiction/typescript-book/a5b2250c7332fe10b04a281e3aad19d75bf0aea4/images/promise states and fates.vsd -------------------------------------------------------------------------------- /images/venn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeFiction/typescript-book/a5b2250c7332fe10b04a281e3aad19d75bf0aea4/images/venn.png -------------------------------------------------------------------------------- /images/venn.vsd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeFiction/typescript-book/a5b2250c7332fe10b04a281e3aad19d75bf0aea4/images/venn.vsd -------------------------------------------------------------------------------- /snippets/md-snippets.cson: -------------------------------------------------------------------------------- 1 | '.source.gfm': 2 | 'include': 3 | 'prefix': 'include' 4 | 'body': """ 5 | {% include "${1:./path}.md" %} 6 | """ --------------------------------------------------------------------------------