├── .gitignore ├── .vscode ├── init.sh └── settings.json ├── README.md ├── basic-types ├── any.ts ├── array.ts ├── boolean.ts ├── intro │ ├── entities │ │ └── entities.ts │ ├── intro.ts │ └── strict-null-check │ │ ├── intro.js │ │ ├── intro.ts │ │ └── tsconfig.json ├── never.ts ├── null.ts ├── number.ts ├── object.ts ├── string.ts ├── symbol.ts ├── tuple.js ├── tuple.ts ├── undefined.ts ├── unknown.ts └── void.ts ├── classes ├── .gitignore ├── abstract-class-with-abstract-methods.ts ├── abstract-class.ts ├── access-modifier-private.ts ├── access-modifier-protected.ts ├── class-interface-with-abstract-methods.ts ├── class-interface.ts ├── class.ts ├── default-property-values.ts ├── ecmascript-private-properties.ts ├── factory-function-typeof-class.ts ├── factory-function.ts ├── implementing-interface.ts ├── inheritance-method-overriding.ts ├── inheritance.ts ├── instance-method-arrow.ts ├── instance-method-bind.ts ├── instance-method-incorrect.ts ├── instance-method.ts ├── interface-extends-class.ts ├── parameter-properties.ts ├── property-accessors.ts └── static-properties.ts ├── compilatiton └── files │ ├── a.ts │ ├── p.js │ ├── src │ ├── b.ts │ ├── c.ts │ ├── lib │ │ ├── d.ts │ │ └── e.ts │ └── q.js │ ├── tsconfig.json │ └── tsconfig.prod.json ├── data-immutability ├── const-keyword.js ├── const-keyword.ts ├── object-freeze.ts ├── property-descriptor.ts ├── read-only-array.ts ├── read-only-tuple.ts ├── readonly-class-field.js ├── readonly-class-field.ts ├── readonly-interface-field.js └── readonly-interface-field.ts ├── declaration-files ├── ambient-declaration │ ├── .gitignore │ ├── program.ts │ ├── tsconfig.json │ └── types │ │ └── common │ │ ├── functions.d.ts │ │ ├── interfaces.d.ts │ │ ├── main.d.ts │ │ └── package.json ├── custom-package │ ├── .gitignore │ ├── human-test.ts │ ├── local-declaration-test.ts │ ├── local-declaration.d.ts │ ├── package-lock.json │ ├── package.json │ ├── packages │ │ ├── human │ │ │ └── package.json │ │ └── person │ │ │ ├── package.json │ │ │ └── person.d.ts │ ├── person-test.ts │ ├── tsconfig.json │ └── types │ │ ├── common │ │ ├── functions.d.ts │ │ ├── interfaces.d.ts │ │ ├── main.d.ts │ │ └── package.json │ │ └── human-types │ │ └── index.d.ts ├── definitely-typed-lodash │ ├── .gitignore │ ├── package-lock.json │ ├── package.json │ ├── program.ts │ ├── tsconfig.json │ └── types │ │ └── common │ │ ├── functions.d.ts │ │ ├── interfaces.d.ts │ │ ├── main.d.ts │ │ └── package.json ├── definitely-typed │ ├── .gitignore │ ├── package-lock.json │ ├── package.json │ ├── program.ts │ ├── tsconfig.json │ └── types │ │ └── common │ │ ├── functions.d.ts │ │ ├── interfaces.d.ts │ │ ├── main.d.ts │ │ └── package.json ├── extend-type-intro │ ├── .gitignore │ ├── program.ts │ ├── tsconfig.json │ └── types │ │ └── common │ │ ├── functions.d.ts │ │ ├── interfaces.d.ts │ │ ├── main.d.ts │ │ └── package.json ├── extend-type-module-intro-fix │ ├── .gitignore │ ├── .gitignore copy │ ├── program.ts │ ├── tsconfig.json │ └── types │ │ └── common │ │ ├── functions.d.ts │ │ ├── interfaces.d.ts │ │ ├── main.d.ts │ │ └── package.json ├── extend-type-module-intro │ ├── .gitignore │ ├── .gitignore copy │ ├── program.ts │ ├── tsconfig.json │ └── types │ │ └── common │ │ ├── functions.d.ts │ │ ├── interfaces.d.ts │ │ ├── main.d.ts │ │ └── package.json ├── intro │ ├── .gitignore │ ├── global-type-promise-peek.ts │ ├── program.ts │ ├── tsconfig.json │ └── types │ │ └── common │ │ ├── main.d.ts │ │ └── package.json ├── modularity │ ├── .gitignore │ ├── program.ts │ ├── tsconfig.json │ └── types │ │ └── common │ │ ├── functions.d.ts │ │ ├── interfaces.d.ts │ │ ├── main.d.ts │ │ └── package.json └── namespacing │ ├── .gitignore │ ├── program.ts │ ├── tsconfig.json │ └── types │ └── common │ ├── functions.d.ts │ ├── interfaces.d.ts │ ├── main.d.ts │ └── package.json ├── decorators ├── .gitignore ├── accessor-decorator.ts ├── class-decorator-extend.ts ├── class-decorator-factory.ts ├── class-decorator.ts ├── decoration-order.ts ├── decorator-chaining.ts ├── emit-decorator-metadata.ts ├── method-decorator.ts ├── package-lock.json ├── package.json ├── parameter-decorator.ts ├── property-decorator-reflect.ts ├── property-decorator.ts └── tsconfig.json ├── enums ├── .gitignore ├── enum-as-type.ts ├── enum-computed-member.ts ├── enum-const.ts ├── enum-js-object.ts ├── enum-member-as-type.ts ├── enum-member-values.ts ├── enum-non-const.ts ├── enum-permission.ts ├── enum-reverse-mapping.ts ├── enum-string.ts └── enum.ts ├── functions ├── currying-concrete-type.ts ├── currying-native-type.ts ├── function-alias-type.ts ├── function-arrow-expression.ts ├── function-declaration.ts ├── function-default-parameter-values.ts ├── function-expression.ts ├── function-optional-parameters.ts ├── function-overloading.ts ├── function-rest-parameters.ts ├── function-spread-operator.ts ├── function-type-with-alias.ts ├── function-typed-expression.ts └── vanilla-function.js ├── generics ├── .gitignore ├── generic-class-factory.ts ├── generic-class.ts ├── generic-constraints-function.ts ├── generic-constraints-union-with-union.ts ├── generic-constraints-union.ts ├── generic-function-multiple-placeholders.ts ├── generic-interface-extended.ts ├── generic-interface-for-class-instance-side.ts ├── generic-interface-function-type.ts ├── generic-interface.ts ├── simple-function.ts └── simple-generic-function.ts ├── hello-world ├── hello-world-with-tsconfig │ ├── build │ │ ├── lib │ │ │ └── utils.js │ │ └── program.js │ ├── dist │ │ ├── lib │ │ │ └── utils.js │ │ └── program.js │ ├── src │ │ ├── lib │ │ │ └── utils.ts │ │ └── program.ts │ └── tsconfig.json ├── hello-world-with-types │ ├── dist │ │ ├── lib │ │ │ └── utils.js │ │ └── program.js │ └── src │ │ ├── lib │ │ └── utils.ts │ │ └── program.ts └── hello-world │ ├── hello.js │ └── hello.ts ├── interfaces ├── .gitignore ├── argument-with-interface.ts ├── argument-with-shape.ts ├── extend-interface.ts ├── extend-multiple-interfaces.ts ├── function-signature-with-methods.ts ├── function-signature-with-new.ts ├── function-signature.ts ├── indexable-type-number.ts ├── indexable-type-object.ts ├── indexable-type-required-properties.ts ├── interface-safety.ts ├── merged-interface.ts ├── nested-interface.ts ├── nested-shape.ts ├── object-shape.ts ├── optional-properties-safety-override.ts ├── optional-properties-safety.ts ├── optional-properties.ts ├── readonly-properties.ts ├── shape-override-any.ts └── shape-override.ts ├── introduction ├── fixed │ ├── program-fixed.js │ └── program-fixed.ts ├── initial │ ├── program.js │ └── program.ts ├── raw │ └── program.js └── target-tsconfig │ └── tsconfig.json ├── module-system ├── .gitignore ├── dist │ ├── api.d.ts │ ├── models │ │ ├── Institution.d.ts │ │ ├── Role.d.ts │ │ └── types.d.ts │ └── utils │ │ └── getAge.d.ts ├── lib │ ├── api.ts │ ├── models │ │ ├── Institution.ts │ │ ├── Role.ts │ │ └── types.ts │ └── utils │ │ └── getAge.ts ├── package-lock.json ├── package.json ├── src │ └── program.ts ├── tsconfig.json └── tsconfig.publish.json ├── polymorphism ├── class-polymorphism.ts ├── instanceof-operator.js └── interface-polymorphism.ts ├── promises-and-async-await ├── .gitignore ├── async-await-reject.ts ├── async-await-try-catch.ts ├── async-await.ts ├── promise-all-reject.ts ├── promise-all-settled.ts ├── promise-all.ts ├── promise-chaining.ts ├── promise-race.ts ├── promise-reject.ts ├── promise-resolve.ts ├── promise.ts └── tsconfig.json ├── type-system ├── .gitignore ├── any-type-guard.ts ├── any-type-issues.ts ├── declare-keyword.ts ├── intersection-common-properties.ts ├── intersection.ts ├── script-vs-module │ ├── module │ │ ├── main.ts │ │ ├── tsconfig.json │ │ └── vendor.ts │ └── script │ │ ├── main.ts │ │ ├── tsconfig.json │ │ └── vendor.ts ├── structural-subtyping.ts ├── structural-typing-interfaces.ts ├── structural-typing.ts ├── type-assertion-correct.ts ├── type-assertion-incorrect.ts ├── type-assertion.ts ├── type-guard-in-operator.ts ├── type-guard-instanceof.ts ├── type-guard-typeof-function.ts ├── type-guard-typeof-property.ts ├── type-guard-user-defined.ts ├── type-inference.ts ├── type-union-gender-correct.ts ├── type-union-gender-incorrect.ts ├── type-union-keyof.ts ├── type-union-with-interfaces-discriminated-union.ts ├── type-union-with-interfaces-incorrect.ts ├── type-union-with-interfaces-type-assertion.ts ├── typeof-keyword.ts ├── unit-type-assertion.ts ├── unit-type-implementation.ts └── unit-type.ts ├── utility-types ├── extract-exclude.ts ├── nonnullable.ts ├── partial.ts ├── pick-omit.ts ├── readonly.js ├── readonly.ts └── record.ts └── webpack-setup ├── dist ├── main.js └── main.js.map ├── index.html ├── package-lock.json ├── package.json ├── src ├── index.ts └── lib │ └── classes.ts ├── tsconfig.json ├── webpack.config.js └── webpack.excalidraw /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.vscode/init.sh: -------------------------------------------------------------------------------- 1 | export PS1='🔥 ' 2 | 3 | # commit alias 4 | commit() { 5 | git add -A && git commit -m "$*" 6 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // integrated terminal settings 3 | "terminal.integrated.shell.osx": "/bin/bash", 4 | "terminal.integrated.shellArgs.osx": [ 5 | "--init-file", ".vscode/init.sh" 6 | ], 7 | 8 | // VSCode UI settings 9 | "workbench.activityBar.visible": false, 10 | "workbench.statusBar.visible": false, 11 | "window.title": "${activeEditorShort}", 12 | "editor.foldingHighlight": false, 13 | "editor.renderLineHighlight": "none", 14 | "editor.occurrencesHighlight": false, 15 | "editor.selectionHighlight": false, 16 | "editor.matchBrackets": "never", 17 | "editor.minimap.enabled": false, 18 | 19 | // disable git 20 | "git.enabled": false, 21 | "gitlens.mode.active": "zen", 22 | "gitlens.codeLens.enabled": false, 23 | 24 | // custom CSS plugin config 25 | // https://marketplace.visualstudio.com/items?itemName=iocave.customize-ui 26 | "customizeUI.stylesheet": { 27 | ".tabs-and-actions-container .editor-actions": "display: none !important;", 28 | ".split-view-container .split-view-view:nth-child(2) .part.panel.bottom .composite.title .title-actions": "display: none !important", 29 | ".monaco-workbench .part.titlebar > .window-title": "display: none !important", 30 | ".monaco-workbench .part.titlebar": "background-color: rgb(37, 37, 38) !important", 31 | ".decorationsOverviewRuler": "opacity: 0 !important", 32 | ".monaco-scrollable-element>.visible": "opacity: 0 !important", 33 | ".monaco-workbench .monaco-scrollable-element > .scrollbar > .slider": "opacity: 0 !important", 34 | ".editor-container": "margin-top: 10px !important;", 35 | ".monaco-editor .scroll-decoration": "box-shadow: unset !important;", 36 | ".monaco-workbench .part.editor>.content .editor-group-container>.title .tabs-container>.tab": "background-color: transparent !important;", 37 | ".monaco-workbench .part.panel.bottom .composite.title": "margin-bottom: 10px !important;", 38 | } 39 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # getting-started-with-typescript 2 | Source code of: https://medium.com/jspoint/typescript/home 3 | 4 | > Working In Progress 5 | -------------------------------------------------------------------------------- /basic-types/any.ts: -------------------------------------------------------------------------------- 1 | // declare a variable of type `any` 2 | let value: any = null; 3 | 4 | // reassign with a `string` value 5 | value = 'Hello World'; 6 | console.log( value ); 7 | 8 | // reassign with a `number` value 9 | value = 1234; 10 | console.log( value ); 11 | 12 | // reassign with a `boolean` value 13 | value = true; 14 | console.log( value ); 15 | 16 | // reassign with a `symbol` value 17 | value = Symbol(); 18 | console.log( value ); 19 | 20 | // reassign with a `undefined` value 21 | value = undefined; 22 | console.log( value ); 23 | 24 | // reassign with a `null` value 25 | value = null; 26 | console.log( value ); 27 | 28 | // reassign with a `object` value 29 | value = { a: 1 }; 30 | console.log( value ); -------------------------------------------------------------------------------- /basic-types/array.ts: -------------------------------------------------------------------------------- 1 | // define an array of `string` elements 2 | let fruits: string[] = [ 'Apple', 'Mango', 'Banana' ]; 3 | fruits.push( 123 ); 4 | 5 | // define an array of `number` elements 6 | let lapTimes: Array = [ 12.05, 13, 11.5 ]; 7 | lapTimes.push( 'orange' ); 8 | 9 | // define any array of `any` elements 10 | let garbage: any[] = [ 'Mango', null, 12.5, undefined, true ]; 11 | garbage.push( 123 ); 12 | garbage.push( 'orange' ); -------------------------------------------------------------------------------- /basic-types/boolean.ts: -------------------------------------------------------------------------------- 1 | // declare a variable of type `boolean` 2 | let isActive: boolean = false; 3 | console.log( "isActive =>", isActive ); 4 | 5 | // reassign using `literal` notation 6 | isActive = true; 7 | console.log( "isActive =>", isActive ); 8 | 9 | // reassign using `constructor` notation 10 | isActive = Boolean( 0 ); 11 | console.log( "isActive =>", isActive ); 12 | 13 | // print runtime type 14 | console.log( "typeof `isActive` at runtime =>", typeof isActive ); -------------------------------------------------------------------------------- /basic-types/intro/entities/entities.ts: -------------------------------------------------------------------------------- 1 | // variables & constants 2 | const fullName: string = 'Ross Geller'; // 'const' declarations must be initialized 3 | var age: number; 4 | let email: string; 5 | 6 | // function declaration 7 | function canVote( age: number ): boolean { 8 | return age >= 18; // `true` if `age` is GTE `18` 9 | } 10 | 11 | // class declaration 12 | class Person { 13 | 14 | // properties declaration 15 | firstName: string; 16 | lastName: string; 17 | age: number; 18 | email: string; 19 | 20 | // constructor declaration 21 | constructor( fn: string, ln: string ) { 22 | this.firstName = fn; 23 | this.lastName = ln; 24 | } 25 | 26 | // method declaration 27 | canVote( age: number ): boolean { 28 | return age >= 18; // `true` if `age` is GTE `18` 29 | } 30 | } 31 | 32 | // object declaration 33 | let person: { 34 | firstName: string; 35 | lastName: string; 36 | age: number; 37 | email: string; 38 | }; -------------------------------------------------------------------------------- /basic-types/intro/intro.ts: -------------------------------------------------------------------------------- 1 | // variable declarations 2 | let person: string; 3 | let age: number = null; 4 | let car: string = 'Mercedes'; 5 | let canDrive: boolean = false; 6 | console.log( `before => (person:${person}), (age:${age}), (car:${car}), (canDrive:${canDrive})` ); 7 | 8 | // override values 9 | person = 'Ross Geller'; 10 | age = 21; 11 | car = undefined; 12 | canDrive = null; 13 | console.log( `before => (person:${person}), (age:${age}), (car:${car}), (canDrive:${canDrive})` ); -------------------------------------------------------------------------------- /basic-types/intro/strict-null-check/intro.js: -------------------------------------------------------------------------------- 1 | // variable declarations 2 | var person; 3 | var age = null; 4 | var car = 'Mercedes'; 5 | var canDrive = false; 6 | console.log("before => (person:" + person + "), (age:" + age + "), (car:" + car + "), (canDrive:" + canDrive + ")"); 7 | // override values 8 | person = 'Ross Geller'; 9 | age = 21; 10 | car = undefined; 11 | canDrive = null; 12 | console.log("before => (person:" + person + "), (age:" + age + "), (car:" + car + "), (canDrive:" + canDrive + ")"); 13 | -------------------------------------------------------------------------------- /basic-types/intro/strict-null-check/intro.ts: -------------------------------------------------------------------------------- 1 | // variable declarations 2 | let person: string; 3 | let age: number = null; 4 | let car: string = 'Mercedes'; 5 | let canDrive: boolean = false; 6 | console.log( `before => (person:${person}), (age:${age}), (car:${car}), (canDrive:${canDrive})` ); 7 | 8 | // override values 9 | person = 'Ross Geller'; 10 | age = 21; 11 | car = undefined; 12 | canDrive = null; 13 | console.log( `before => (person:${person}), (age:${age}), (car:${car}), (canDrive:${canDrive})` ); -------------------------------------------------------------------------------- /basic-types/intro/strict-null-check/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ "./intro.ts" ], 3 | "compilerOptions": { 4 | "strictNullChecks": true 5 | } 6 | } -------------------------------------------------------------------------------- /basic-types/never.ts: -------------------------------------------------------------------------------- 1 | // this functions throws an error, hence never returns 2 | function oops(): never { 3 | throw new Error(); 4 | } 5 | 6 | // this function runs endless `while` loop, hence never returns 7 | function blackHole(): never { 8 | while( true ) {} 9 | } -------------------------------------------------------------------------------- /basic-types/null.ts: -------------------------------------------------------------------------------- 1 | // declare a variable of type `null` 2 | let value: null; 3 | console.log( "value =>", value ); 4 | 5 | // reassign with the `undefined` value (when `strictNullChecks` is false) 6 | value = undefined; 7 | console.log( "value =>", value ); 8 | 9 | // reassign using `literal` notation 10 | value = null; 11 | console.log( "value =>", value ); 12 | 13 | // print runtime type 14 | console.log( "typeof `value` at runtime =>", typeof value ); -------------------------------------------------------------------------------- /basic-types/number.ts: -------------------------------------------------------------------------------- 1 | // declare a variable of type `number` 2 | let size: number = 50; 3 | console.log( "size =>", size ); 4 | 5 | // reassign using `literal` notation 6 | size = 60.5; 7 | console.log( "size =>", size ); 8 | 9 | // reassign using `constructor` notation 10 | size = Number( '100' ); 11 | console.log( "size =>", size ); 12 | 13 | // print runtime type 14 | console.log( "typeof `size` at runtime =>", typeof size ); -------------------------------------------------------------------------------- /basic-types/object.ts: -------------------------------------------------------------------------------- 1 | // declare a variable of type `object` 2 | let obj: object = { name: 'John Doe' }; 3 | 4 | // legal assigment with non-primitives 5 | obj = [ 1, 2, 3 ]; // Array 6 | console.log( 'typeof obj =>', typeof obj ); // object 7 | 8 | obj = { age: 21 }; // Object 9 | console.log( 'typeof obj =>', typeof obj ); // object 10 | 11 | obj = () => null; // Function 12 | console.log( 'typeof obj =>', typeof obj ); // function 13 | 14 | /*-------------------*/ 15 | 16 | // illegal assigment with primitives 17 | obj = 'John Doe'; 18 | obj = 21; 19 | obj = Symbol(); 20 | obj = true; 21 | obj = undefined; 22 | obj = null; -------------------------------------------------------------------------------- /basic-types/string.ts: -------------------------------------------------------------------------------- 1 | // declare a variable of type `string` 2 | let fruit: string = 'Mango'; 3 | console.log( "fruit =>", fruit ); 4 | 5 | // reassign using `literal` notation (template string) 6 | fruit = `${ fruit } or Apple`; 7 | console.log( "fruit =>", fruit ); 8 | 9 | // reassign using `constructor` notation 10 | fruit = String( 100 ); 11 | console.log( "fruit =>", fruit ); 12 | 13 | // print runtime type 14 | console.log( "typeof `fruit` at runtime =>", typeof fruit ); -------------------------------------------------------------------------------- /basic-types/symbol.ts: -------------------------------------------------------------------------------- 1 | // declare variables of type `symbol` 2 | var symbol1: symbol = Symbol(); 3 | var symbol2 = Symbol(); // infers the type `symbol` 4 | 5 | console.log( 'symbol1 =>', symbol1 ); 6 | console.log( 'typeof symbol1 =>', typeof symbol1 ); 7 | console.log( 'symbol1 === symbol2 =>', symbol1 === symbol2 ); 8 | 9 | /*-----------*/ 10 | 11 | // each `Symbol()` expression generate a unique `symbol` value 12 | var symbol3 = Symbol('name'); 13 | var symbol4 = Symbol('name'); 14 | 15 | console.log( 'symbol3 =>', symbol3 ); 16 | console.log( 'symbol3 === symbol4 =>', symbol3 === symbol4 ); 17 | 18 | /*-----------*/ 19 | 20 | // symbol value can also be used as an object key 21 | var colorKey: symbol = Symbol('color'); 22 | var myCar = { model: 'Audi Q5', [ colorKey ]: 'Red' }; 23 | 24 | console.log( 'myCar =>', myCar ); 25 | // @ts-ignore 26 | console.log( 'myCar[colorKey] =>', myCar[ colorKey ] ); 27 | console.log( 'Object.keys(myCar) =>', Object.keys( myCar ) ); -------------------------------------------------------------------------------- /basic-types/tuple.js: -------------------------------------------------------------------------------- 1 | // define a tuple 2 | var student = ['Ross Geller', 27, true]; 3 | // legal: override values 4 | student = ['Monica Geller', 25, false]; 5 | student[1] = 28; 6 | // illegal: override values 7 | student = [true, 'Mike Doe', false]; 8 | student[1] = false; 9 | -------------------------------------------------------------------------------- /basic-types/tuple.ts: -------------------------------------------------------------------------------- 1 | // define a tuple 2 | let student: [ string, number, boolean ] = [ 'Ross Geller', 27, true ]; 3 | 4 | // legal: override values 5 | student = [ 'Monica Geller', 25, false ]; 6 | student[1] = 28; 7 | 8 | // illegal: override values 9 | student = [ true, 'Mike Doe', false ]; 10 | student[1] = false; -------------------------------------------------------------------------------- /basic-types/undefined.ts: -------------------------------------------------------------------------------- 1 | // declare a variable of type `undefined` 2 | let secret: undefined; 3 | console.log( "secret =>", secret ); 4 | 5 | // reassign with the `null` value (when `strictNullChecks` is false) 6 | secret = null; 7 | console.log( "secret =>", secret ); 8 | 9 | // reassign using `literal` notation 10 | secret = undefined; 11 | console.log( "secret =>", secret ); 12 | 13 | // print runtime type 14 | console.log( "typeof `secret` at runtime =>", typeof secret ); -------------------------------------------------------------------------------- /basic-types/unknown.ts: -------------------------------------------------------------------------------- 1 | // declare variables of type `any` and `unknown` 2 | let valueA: any = null; 3 | let valueB: unknown = null; 4 | 5 | // reassign with a `string` value 6 | valueA = 'Hello World'; 7 | valueB = 'Hello World'; 8 | 9 | // declare a variable of type `number` with 10 | // an initial value of `valueA` 11 | let boolA: number = valueA; 12 | 13 | // declare a variable of type `number` with 14 | // an initial value of `valueB` 15 | let boolB: number = valueB; 16 | 17 | // access properties/methods of `valueA` and `valueB` 18 | valueA.toUpperCase(); 19 | valueB.toUpperCase(); 20 | 21 | // call `valueA` and `valueB` 22 | valueA(); 23 | valueB(); -------------------------------------------------------------------------------- /basic-types/void.ts: -------------------------------------------------------------------------------- 1 | // function does not return a value 2 | function sayHello(): void { 3 | console.log( "Hello World!" ); 4 | } 5 | 6 | // variable of type `void` can represent `undefined` 7 | let empty: void = undefined; 8 | 9 | // call `sayHello` function 10 | sayHello(); -------------------------------------------------------------------------------- /classes/.gitignore: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /classes/abstract-class-with-abstract-methods.ts: -------------------------------------------------------------------------------- 1 | abstract class Person { 2 | constructor( public firstName: string, public lastName: string ){} 3 | 4 | getFullName(): string { 5 | return `${ this.firstName } ${ this.lastName }`; 6 | } 7 | } 8 | 9 | class Student extends Person { 10 | constructor( firstName: string, lastName: string, public marks: number ){ 11 | super( firstName, lastName ); 12 | } 13 | 14 | getGrade(): string { 15 | return (this.marks / 10).toFixed( 0 ); 16 | } 17 | } 18 | 19 | // Error: Cannot create an instance of an abstract class.ts 20 | // const ross: Person = new Person( 'Ross', 'Geller' ); 21 | 22 | // create `monica` instance of type `Student` 23 | const monica: Student = new Student( 'Monica', 'Geller', 84 ); 24 | console.log( monica.getFullName() ); // Monica Geller 25 | console.log( monica.getGrade() ); // 8 -------------------------------------------------------------------------------- /classes/abstract-class.ts: -------------------------------------------------------------------------------- 1 | // create an abstract class 2 | abstract class Person { 3 | constructor( 4 | public firstName: string, 5 | public lastName: string 6 | ){} 7 | 8 | getFullName(): string { 9 | return `${ this.firstName } ${ this.lastName }`; 10 | } 11 | } 12 | 13 | // `Student` class inherits `Person` class 14 | class Student extends Person { 15 | constructor( 16 | firstName: string, 17 | lastName: string, 18 | public marks: number 19 | ){ 20 | super( firstName, lastName ); 21 | } 22 | 23 | getGrade(): string { 24 | return (this.marks / 10).toFixed( 0 ); 25 | } 26 | } 27 | 28 | // Error: Cannot create an instance of an abstract class.ts 29 | const ross: Person = new Person( 'Ross', 'Geller' ); 30 | 31 | // create `monica` instance of type `Student` 32 | const monica: Student = new Student( 'Monica', 'Geller', 84 ); 33 | console.log( monica.getFullName() ); // Monica Geller 34 | console.log( monica.getGrade() ); // 8 -------------------------------------------------------------------------------- /classes/access-modifier-private.ts: -------------------------------------------------------------------------------- 1 | class Person { 2 | private name: string; 3 | public age: number; // `public` is redundant 4 | 5 | constructor( name: string, age: number ) { 6 | this.name = name; 7 | this.age = age; 8 | } 9 | 10 | getNameParts(): string[] { 11 | return this.name.split( ' ' ); 12 | } 13 | 14 | private getAge(): number { 15 | return this.age; 16 | } 17 | } 18 | 19 | // create `ross` instance of type `Person` 20 | const ross: Person = new Person( 'Ross Geller', 30 ); 21 | 22 | // legal 23 | console.log( ross.age ); 24 | console.log( ross.getNameParts() ); 25 | 26 | // Error: Property 'name' is private and only accessible 27 | // within class 'Person'. 28 | console.log( ross.name ); 29 | 30 | // Error: Property 'getAge' is private and only accessible 31 | // within class 'Person'. 32 | console.log( ross.getAge() ); -------------------------------------------------------------------------------- /classes/access-modifier-protected.ts: -------------------------------------------------------------------------------- 1 | // superclass 2 | class Person { 3 | private dob: string; 4 | 5 | constructor( dob: string ) { 6 | this.dob = dob; 7 | } 8 | 9 | protected getAge(): number { 10 | const currentYear = new Date().getFullYear(); 11 | const birthYear = new Date( this.dob ).getFullYear(); 12 | 13 | return currentYear - birthYear; // approx 14 | } 15 | } 16 | 17 | // subclass 18 | class Student extends Person { 19 | public name: string; 20 | 21 | constructor( name: string, dob: string ) { 22 | super( dob ); 23 | this.name = name; 24 | } 25 | 26 | describe(): string { 27 | return `${ this.name } is ${ super.getAge() } years old.`; 28 | } 29 | } 30 | 31 | // create `ross` instance of type `Student` 32 | const ross: Student = new Student( 'Ross Geller', '10-14-1992' ); 33 | 34 | // Error: Property 'dob' is private and only accessible within class 'Person'. 35 | console.log( ross.dob ); // private 36 | 37 | // Property 'getAge' is protected and only accessible within class 'Person' and its subclasses. 38 | console.log( ross.getAge() ); // protected 39 | 40 | // legal 41 | console.log( ross.describe() ); // public -------------------------------------------------------------------------------- /classes/class-interface-with-abstract-methods.ts: -------------------------------------------------------------------------------- 1 | abstract class Person { 2 | constructor( 3 | public firstName: string, 4 | public lastName: string 5 | ){} 6 | 7 | // abstract method declaration 8 | abstract getFullName(): string; 9 | } 10 | 11 | class Student extends Person { 12 | constructor( 13 | firstName: string, 14 | lastName: string, 15 | public marks: number 16 | ){ 17 | super( firstName, lastName ); 18 | } 19 | 20 | getFullName(): string { 21 | return `${ this.firstName } ${ this.lastName }`; 22 | } 23 | 24 | getGrade(): string { 25 | return (this.marks / 10).toFixed( 0 ); 26 | } 27 | } 28 | 29 | // Error: Cannot create an instance of an abstract class. 30 | // const ross: Person = new Person( 'Ross', 'Geller' ); 31 | 32 | // create `monica` instance of type `Student` 33 | const monica: Student = new Student( 'Monica', 'Geller', 84 ); 34 | console.log( monica.getFullName() ); // Monica Geller 35 | console.log( monica.getGrade() ); // 8 -------------------------------------------------------------------------------- /classes/class-interface.ts: -------------------------------------------------------------------------------- 1 | class Person { 2 | constructor( 3 | public firstName: string, 4 | public lastName: string 5 | ){} 6 | 7 | getFullName(): string { 8 | return `${ this.firstName } ${ this.lastName }`; 9 | } 10 | } 11 | 12 | // `Student` class implements the `Person` class 13 | class Student implements Person { 14 | constructor( 15 | public firstName: string, 16 | public lastName: string, 17 | public marks: number 18 | ){} 19 | 20 | getFullName(): string { 21 | return `${ this.firstName } ${ this.lastName }`; 22 | } 23 | 24 | getGrade(): string { 25 | return (this.marks / 10).toFixed( 0 ); 26 | } 27 | } 28 | 29 | // create `ross` instance of type `Person` 30 | const ross: Person = new Person( 'Ross', 'Geller' ); 31 | 32 | // create `monica` instance of type `Student` 33 | const monica: Student = new Student( 'Monica', 'Geller', 84 ); 34 | console.log( monica.getFullName() ); // Monica Geller 35 | console.log( monica.getGrade() ); // 8 -------------------------------------------------------------------------------- /classes/class.ts: -------------------------------------------------------------------------------- 1 | // define a `Person` class 2 | class Person { 3 | firstName: string; 4 | lastName: string; 5 | age: number; 6 | 7 | constructor( firstName: string, lastName: string, age: number ) { 8 | this.firstName = firstName; 9 | this.lastName = lastName; 10 | this.age = age; 11 | } 12 | 13 | getFullName(): string { 14 | return `${ this.firstName } ${ this.lastName }`; 15 | } 16 | } 17 | 18 | // create an instance of `Person` class 19 | const ross: Person = new Person( 'Ross', 'Geller', 30 ); 20 | 21 | // print full-name of `ross` 22 | console.log( 'ross.getFullName() =>', ross.getFullName() ); -------------------------------------------------------------------------------- /classes/default-property-values.ts: -------------------------------------------------------------------------------- 1 | class Person { 2 | firstName: string; 3 | lastName: string; 4 | age: number = 28; 5 | type = 'person'; 6 | 7 | constructor( firstName: string, lastName: string, age?: number ) { 8 | this.firstName = firstName; 9 | this.lastName = lastName; 10 | 11 | // override `age` value if provided by the user 12 | if( age !== undefined ) { 13 | this.age = age; 14 | } 15 | } 16 | } 17 | 18 | // create an instance of `Person` class 19 | const ross: Person = new Person( 'Ross', 'Geller' ); 20 | console.log( 'ross =>', ross ); -------------------------------------------------------------------------------- /classes/ecmascript-private-properties.ts: -------------------------------------------------------------------------------- 1 | class Person { 2 | // TypeScript private 3 | private name: string; 4 | 5 | // TypeScript and JavaScript private 6 | #dob: Date; 7 | 8 | constructor( name: string, dob: Date ){ 9 | this.name = name; 10 | this.#dob = dob; 11 | } 12 | 13 | getBirthYear(): number { 14 | return this.#dob.getFullYear(); 15 | } 16 | } 17 | 18 | // create `ross` instance of type `Person` 19 | const ross: Person = new Person( 20 | 'Ross Geller', new Date( '10-14-1992' ) 21 | ); 22 | 23 | // Error: Property '#dob' is not accessible outside class 'Person' because it has a private identifier. 24 | console.log( ross.#dob ); -------------------------------------------------------------------------------- /classes/factory-function-typeof-class.ts: -------------------------------------------------------------------------------- 1 | // `Person` as a type represents instance side of the class 2 | class Person { 3 | constructor( 4 | public firstName: string, 5 | public lastName: string 6 | ) {} 7 | 8 | getFullName(): string { 9 | return `${ this.firstName } ${ this.lastName }`; 10 | } 11 | 12 | // static fields 13 | static delimiter = ' '; 14 | static splitName( name: string, separator: string ): string[] { 15 | return name.split( separator ); 16 | } 17 | } 18 | 19 | // factory function 20 | let createPerson = function( ctor: typeof Person, name: string ) { 21 | let [ firstName, lastName ] = ctor.splitName( name, ctor.delimiter ); 22 | return new ctor( firstName, lastName ); 23 | } 24 | 25 | // create an instance of `Person` class 26 | const ross: Person = createPerson( Person, 'Ross Geller' ); 27 | 28 | // print full-name of `ross` 29 | console.log( ross.getFullName() ); -------------------------------------------------------------------------------- /classes/factory-function.ts: -------------------------------------------------------------------------------- 1 | // `Person` as a type represents instance side of the class 2 | class Person { 3 | constructor( 4 | public firstName: string, 5 | public lastName: string 6 | ) {} 7 | 8 | getFullName(): string { 9 | return `${ this.firstName } ${ this.lastName }`; 10 | } 11 | 12 | // static fields 13 | static delimiter = ' '; 14 | static splitName( name: string, separator: string ): string[] { 15 | return name.split( separator ); 16 | } 17 | } 18 | 19 | // this interface represents static side of the `Person` class 20 | interface PersonInterface{ 21 | new ( firstName: string, lastName: string ): Person; // constructor 22 | delimiter: string; // static property 23 | splitName( name: string, separator: string ): string[]; // static method 24 | } 25 | 26 | // factory function 27 | let createPerson = function( ctor: PersonInterface, name: string ): Person { 28 | let [ firstName, lastName ] = ctor.splitName( name, ctor.delimiter ); 29 | return new ctor( firstName, lastName ); 30 | } 31 | 32 | // create an instance of `Person` class 33 | const ross: Person = createPerson( Person, 'Ross Geller' ); 34 | 35 | // print full-name of `ross` 36 | console.log( ross.getFullName() ); -------------------------------------------------------------------------------- /classes/implementing-interface.ts: -------------------------------------------------------------------------------- 1 | // define an interface 2 | interface PersonInterface { 3 | firstName: string; 4 | lastName: string; 5 | dob: Date; 6 | readonly name: string; 7 | getBirthYear(): number; 8 | } 9 | 10 | // class implements the interface 11 | class Person implements PersonInterface{ 12 | constructor( 13 | public firstName: string, 14 | public lastName: string, 15 | public dob: Date 16 | ){} 17 | 18 | get name(): string { 19 | return `${ this.firstName } ${ this.lastName }`; 20 | } 21 | 22 | getBirthYear(): number { 23 | return this.dob.getFullYear(); 24 | } 25 | } 26 | 27 | // create `ross` instance of type `Person` 28 | const ross: Person = new Person( 29 | 'Ross', 30 | 'Geller', 31 | new Date( '10-14-1992' ) 32 | ); 33 | 34 | console.log( 'ross =>', ross ); -------------------------------------------------------------------------------- /classes/inheritance-method-overriding.ts: -------------------------------------------------------------------------------- 1 | // superclass 2 | class Person { 3 | name: string; 4 | 5 | constructor( name: string ) { 6 | this.name = name; 7 | } 8 | 9 | getNameParts(): string[] { 10 | return this.name.split( ' ' ); 11 | } 12 | } 13 | 14 | // subclass 15 | class Student extends Person { 16 | marks: number; 17 | 18 | constructor( name: string, marks: number ) { 19 | super( name ); // `Person` constructor call 20 | this.marks = marks; 21 | } 22 | 23 | getNameParts(): string[] { 24 | // parent method call 25 | const nameParts = super.getNameParts(); 26 | 27 | return nameParts.map( part => part.toUpperCase() ); 28 | } 29 | } 30 | 31 | // create an instance of `Student` class 32 | const ross: Student = new Student( 'Ross Geller', 86 ); 33 | 34 | console.log( 'ross =>', ross ); 35 | console.log( 'ross.getNameParts() =>', ross.getNameParts() ); -------------------------------------------------------------------------------- /classes/inheritance.ts: -------------------------------------------------------------------------------- 1 | // superclass 2 | class Person { 3 | name: string; 4 | 5 | constructor( name: string ) { 6 | this.name = name; 7 | } 8 | 9 | getNameParts(): string[] { 10 | return this.name.split( ' ' ); 11 | } 12 | } 13 | 14 | // subclass 15 | class Student extends Person { 16 | marks: number; 17 | 18 | constructor( name: string, marks: number ) { 19 | super( name ); // `Person` constructor call 20 | this.marks = marks; 21 | } 22 | 23 | getGrade(): string { 24 | return (this.marks / 10).toFixed( 0 ); 25 | } 26 | } 27 | 28 | // create an instance of `Student` class 29 | const ross: Student = new Student( 'Ross Geller', 86 ); 30 | 31 | console.log( 'ross =>', ross ); 32 | console.log( 'ross.getGrade() =>', ross.getGrade() ); 33 | console.log( 'ross.getNameParts() =>', ross.getNameParts() ); -------------------------------------------------------------------------------- /classes/instance-method-arrow.ts: -------------------------------------------------------------------------------- 1 | class Person { 2 | constructor( public name: string ) {} 3 | 4 | // instance method 5 | getName = (): string => { 6 | return this.name; 7 | } 8 | } 9 | 10 | // create `ross` instance of type `Person` 11 | const ross: Person = new Person( 'Ross Geller' ); 12 | 13 | console.log( 'ross =>', ross ); 14 | console.log( 'ross.getName() =>', ross.getName() ); 15 | 16 | // save `ross.getName` in `getNameFn` 17 | let getNameFn = ross.getName; 18 | console.log( 'getNameFn() =>', getNameFn() ); -------------------------------------------------------------------------------- /classes/instance-method-bind.ts: -------------------------------------------------------------------------------- 1 | class Person { 2 | constructor( public name: string ) { 3 | 4 | // bind `getName` method to `this`. 5 | this.getName = this.getName.bind( this ); 6 | } 7 | 8 | getName(): string { 9 | return this.name; 10 | } 11 | } 12 | 13 | // create `ross` instance of type `Person` 14 | const ross: Person = new Person( 'Ross Geller' ); 15 | 16 | console.log( 'ross =>', ross ); 17 | console.log( 'ross.getName() =>', ross.getName() ); 18 | 19 | // save `ross.getName` in `getNameFn` 20 | let getNameFn = ross.getName; 21 | console.log( 'getNameFn() =>', getNameFn() ); -------------------------------------------------------------------------------- /classes/instance-method-incorrect.ts: -------------------------------------------------------------------------------- 1 | class Person { 2 | constructor( public name: string ) {} 3 | 4 | getName(): string { 5 | return this.name; 6 | } 7 | } 8 | 9 | // create `ross` instance of type `Person` 10 | const ross: Person = new Person( 'Ross Geller' ); 11 | console.log( 'ross.getName() =>', ross.getName() ); 12 | 13 | // save `ross.getName` in `getNameFn` 14 | let getNameFn = ross.getName; 15 | console.log( 'ross.name =>', ross.name ); 16 | console.log( 'getNameFn() =>', getNameFn() ); -------------------------------------------------------------------------------- /classes/instance-method.ts: -------------------------------------------------------------------------------- 1 | class Person { 2 | constructor( public name: string ) {} 3 | 4 | // instance method 5 | getName(): string { 6 | return this.name; 7 | } 8 | } 9 | 10 | // create `ross` instance of type `Person` 11 | const ross: Person = new Person( 'Ross Geller' ); 12 | 13 | console.log( 'ross =>', ross ); 14 | console.log( 'ross.getName() =>', ross.getName() ); 15 | 16 | // save `ross.getName` in `getNameFn` 17 | let getNameFn = ross.getName; 18 | console.log( 'getNameFn() =>', getNameFn() ); -------------------------------------------------------------------------------- /classes/interface-extends-class.ts: -------------------------------------------------------------------------------- 1 | // define a class 2 | class Person { 3 | constructor( 4 | public firstName: string, 5 | public lastName: string 6 | ){} 7 | 8 | getFullName(): string { 9 | return `${ this.firstName } ${ this.lastName }`; 10 | } 11 | } 12 | 13 | // declare an interface that extends a class 14 | interface Student extends Person { 15 | marks: number; 16 | } 17 | 18 | // create `ross` object of type `Student` 19 | const ross: Student = { 20 | firstName: 'Ross', 21 | lastName: 'Geller', 22 | marks: 98 23 | }; -------------------------------------------------------------------------------- /classes/parameter-properties.ts: -------------------------------------------------------------------------------- 1 | // class with parameter properties 2 | class Person { 3 | constructor( public name: string, private age: number ) {} 4 | } 5 | 6 | // create `ross` instance of type `Person` 7 | const ross: Person = new Person( 'Ross Geller', 30 ); 8 | console.log( 'ross =>', ross ); -------------------------------------------------------------------------------- /classes/property-accessors.ts: -------------------------------------------------------------------------------- 1 | class Person { 2 | private _dob: Date; 3 | 4 | constructor( public name: string, dobRaw: string ) { 5 | this._dob = new Date( dobRaw ); 6 | } 7 | 8 | // `dob` property getter 9 | get dob(): string { 10 | const date = this._dob.getDate(); 11 | const month = this._dob.getMonth() + 1; 12 | const year = this._dob.getFullYear(); 13 | 14 | return `${ month }-${ date }-${ year }`; // mm-dd-yyyy 15 | } 16 | 17 | // `dob` property setter 18 | set dob( dobRaw ) { 19 | this._dob = new Date( dobRaw ); 20 | } 21 | } 22 | 23 | // create `ross` instance of type `Person` 24 | const ross: Person = new Person( 'Ross Geller', '10-14-1992' ); 25 | console.log( 'BEFORE / ross =>', ross ); 26 | console.log( 'BEFORE / ross.dob =>', ross.dob ); 27 | 28 | // update date 29 | ross.dob = '10-15-1992'; 30 | console.log( 'AFTER / ross =>', ross ); 31 | console.log( 'AFTER / ross.dob =>', ross.dob ); -------------------------------------------------------------------------------- /classes/static-properties.ts: -------------------------------------------------------------------------------- 1 | class Person { 2 | // statc property 3 | static type: string = 'person'; 4 | 5 | // instance properties 6 | firstName: string; 7 | lastName: string; 8 | 9 | // constructor 10 | constructor( firstName: string, lastName: string ) { 11 | this.firstName = firstName; 12 | this.lastName = lastName; 13 | } 14 | 15 | // static method 16 | static describe(): string { 17 | return `A class of type ${ this.type }.`; 18 | } 19 | 20 | // instance method 21 | getFullName(): string { 22 | return `${ this.firstName } ${ this.lastName }`; 23 | } 24 | } 25 | 26 | // create an instance of `Person` class 27 | const ross: Person = new Person( 'Ross', 'Geller' ); 28 | 29 | console.log( 'Person.type =>', Person.type ); 30 | console.log( 'ross.type =>', (ross as any).type ); 31 | console.log( 'Person.firstName =>', (Person as any).firstName ); 32 | console.log( 'Person.describe() =>', Person.describe() ); -------------------------------------------------------------------------------- /compilatiton/files/a.ts: -------------------------------------------------------------------------------- 1 | import { StringValidator } from "./src/b"; 2 | 3 | export const numberRegexp = /^[0-9]+$/; 4 | 5 | export class ZipCodeValidator implements StringValidator { 6 | isAcceptable(s: string) { 7 | return s.length === 5 && numberRegexp.test(s); 8 | } 9 | } -------------------------------------------------------------------------------- /compilatiton/files/p.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/course-zero/getting-started-with-typescript/d4ff7c0f57fe7e398af12c216fa0e4448612f81b/compilatiton/files/p.js -------------------------------------------------------------------------------- /compilatiton/files/src/b.ts: -------------------------------------------------------------------------------- 1 | export interface StringValidator { 2 | isAcceptable(s: string): boolean; 3 | } 4 | 5 | export const a = 1; -------------------------------------------------------------------------------- /compilatiton/files/src/c.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/course-zero/getting-started-with-typescript/d4ff7c0f57fe7e398af12c216fa0e4448612f81b/compilatiton/files/src/c.ts -------------------------------------------------------------------------------- /compilatiton/files/src/lib/d.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/course-zero/getting-started-with-typescript/d4ff7c0f57fe7e398af12c216fa0e4448612f81b/compilatiton/files/src/lib/d.ts -------------------------------------------------------------------------------- /compilatiton/files/src/lib/e.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/course-zero/getting-started-with-typescript/d4ff7c0f57fe7e398af12c216fa0e4448612f81b/compilatiton/files/src/lib/e.ts -------------------------------------------------------------------------------- /compilatiton/files/src/q.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/course-zero/getting-started-with-typescript/d4ff7c0f57fe7e398af12c216fa0e4448612f81b/compilatiton/files/src/q.js -------------------------------------------------------------------------------- /compilatiton/files/tsconfig.json: -------------------------------------------------------------------------------- 1 | // tsconfig.json 2 | 3 | { 4 | "include": [ 5 | "a.ts", 6 | "src/**/*" 7 | ], 8 | "compilerOptions": { 9 | "outDir": "dist", 10 | "allowJs": true, 11 | "checkJs": true 12 | } 13 | } -------------------------------------------------------------------------------- /compilatiton/files/tsconfig.prod.json: -------------------------------------------------------------------------------- 1 | // tsconfig.json 2 | 3 | { 4 | "extends": "./tsconfig.json", 5 | "compilerOptions": { 6 | "outDir": "dist_prod", 7 | "paths": { 8 | "modules/*": [ "node_modules/*" ] 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /data-immutability/const-keyword.js: -------------------------------------------------------------------------------- 1 | var ross = { 2 | firstName: 'Ross', 3 | lastName: 'Geller' 4 | }; 5 | // update `firstName` property 6 | ross.firstName = 'Jack'; 7 | console.log(ross.firstName); // Jack 8 | // override `ross` value 9 | // Error: Cannot assign to 'ross' because it is a constant 10 | ross = null; 11 | -------------------------------------------------------------------------------- /data-immutability/const-keyword.ts: -------------------------------------------------------------------------------- 1 | const ross = { 2 | firstName: 'Ross', 3 | lastName: 'Geller' 4 | }; 5 | 6 | // update `firstName` property 7 | ross.firstName = 'Jack'; 8 | console.log( ross.firstName ); // Jack 9 | 10 | // override `ross` value 11 | // Error: Cannot assign to 'ross' because it is a constant 12 | ross = null; -------------------------------------------------------------------------------- /data-immutability/object-freeze.ts: -------------------------------------------------------------------------------- 1 | // define a simple object 2 | let ross = { 3 | firstName: 'Ross', 4 | lastName: 'Geller' 5 | }; 6 | 7 | // print initial value 8 | console.log( '[init] ross =>', ross ); 9 | 10 | // update `ross` object 11 | ross.firstName = 'Judy'; // update property value 12 | console.log( '[before] ross =>', ross ); 13 | 14 | // freeze `ross` object 15 | Object.freeze( ross ); 16 | 17 | // update `ross` object 18 | ross.firstName = 'Jack'; // update property value 19 | (ross as any).age = 30; // add new property 20 | console.log( '[after] ross =>', ross ); -------------------------------------------------------------------------------- /data-immutability/property-descriptor.ts: -------------------------------------------------------------------------------- 1 | // define a simple object 2 | let ross = { 3 | firstName: 'Ross', 4 | lastName: 'Geller' 5 | }; 6 | 7 | console.log( '[init] firstName =>', ross.firstName ); 8 | 9 | // simple function to return property descriptor 10 | const getDescriptor = ( obj: object, key: string ) => { 11 | return Object.getOwnPropertyDescriptor( obj, key ); 12 | }; 13 | 14 | // get property descriptor of the `firstName` 15 | const pd = getDescriptor( ross, 'firstName' ); 16 | console.log( 'pd.writable =>', pd.writable ); 17 | 18 | // update `firstName` property 19 | ross.firstName = 'Judy'; 20 | console.log( '[before] firstName =>', ross.firstName ); 21 | 22 | // make `firstName` property readonly 23 | Object.defineProperty( ross, 'firstName', { 24 | writable: false 25 | } ); 26 | const pdAfter = getDescriptor( ross, 'firstName' ); 27 | console.log( 'pd.writable =>', pdAfter.writable ); 28 | 29 | // update `firstName` property value again 30 | ross.firstName = 'Jack'; 31 | console.log( '[after] firstName =>', ross.firstName ); -------------------------------------------------------------------------------- /data-immutability/read-only-array.ts: -------------------------------------------------------------------------------- 1 | // create a readonly array 2 | const oddNumbers: readonly number[] = [ 1, 3, 5, 7, 9 ]; 3 | 4 | // Error: Index signature in type 'readonly number[]' only permits reading. 5 | oddNumbers[ 0 ] = 11; 6 | 7 | // Error: Property 'push' does not exist on type 'readonly number[]'. 8 | oddNumbers.push( 11 ); 9 | 10 | // Error: Property 'pop' does not exist on type 'readonly number[]'. 11 | oddNumbers.pop(); 12 | 13 | // Error: Cannot assign to 'length' because it is a read-only property. 14 | oddNumbers.length = 6; 15 | 16 | // Error: Cannot assign to 'oddNumbers' because it is a constant. 17 | oddNumbers = [ 1, 2, 3 ]; 18 | 19 | // Error: The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'. 20 | let numbers: number[] = oddNumbers; -------------------------------------------------------------------------------- /data-immutability/read-only-tuple.ts: -------------------------------------------------------------------------------- 1 | // create a readonly array 2 | const oddNumbers: readonly [number, string] = [ 1, "1" ]; 3 | 4 | // Error: Index signature in type 'readonly number[]' only permits reading. 5 | oddNumbers[ 0 ] = 11; 6 | 7 | // Error: Property 'push' does not exist on type 'readonly number[]'. 8 | oddNumbers.push( 11 ); 9 | 10 | // Error: Property 'pop' does not exist on type 'readonly number[]'. 11 | oddNumbers.pop(); 12 | 13 | // Error: Cannot assign to 'length' because it is a read-only property. 14 | oddNumbers.length = 6; 15 | 16 | // Error: Cannot assign to 'oddNumbers' because it is a constant. 17 | oddNumbers = [ 1, 2, 3 ]; 18 | 19 | // Error: The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'. 20 | let numbers: number[] = oddNumbers; -------------------------------------------------------------------------------- /data-immutability/readonly-class-field.js: -------------------------------------------------------------------------------- 1 | var Person = /** @class */ (function () { 2 | function Person(firstName, lastName) { 3 | this.firstName = firstName; 4 | this.lastName = lastName; 5 | } 6 | return Person; 7 | }()); 8 | // create `ross` object of type `Person` 9 | var ross = new Person('Ross', 'Geller'); 10 | // update `firstName` property 11 | // Error: Cannot assign to 'firstName' because it is a read-only property. 12 | ross.firstName = 'Jack'; 13 | -------------------------------------------------------------------------------- /data-immutability/readonly-class-field.ts: -------------------------------------------------------------------------------- 1 | class Person { 2 | readonly firstName: string; 3 | public lastName: string; 4 | 5 | constructor( firstName: string, lastName: string ) { 6 | this.firstName = firstName; 7 | this.lastName = lastName; 8 | } 9 | } 10 | 11 | // create `ross` object of type `Person` 12 | let ross: Person = new Person( 'Ross', 'Geller' ); 13 | 14 | // update `firstName` property 15 | // Error: Cannot assign to 'firstName' because it is a read-only property. 16 | ross.firstName = 'Jack'; -------------------------------------------------------------------------------- /data-immutability/readonly-interface-field.js: -------------------------------------------------------------------------------- 1 | // create `ross` object of type `Person` 2 | var ross = { 3 | firstName: 'Ross', 4 | lastName: 'Geller' 5 | }; 6 | // update `lastName` property 7 | ross.lastName = 'Tribbiani'; 8 | // update `firstName` property 9 | // Error: Cannot assign to 'firstName' because it is a read-only property. 10 | ross.firstName = 'Joey'; 11 | -------------------------------------------------------------------------------- /data-immutability/readonly-interface-field.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | readonly firstName: string; // readonly 3 | lastName: string; 4 | } 5 | 6 | // create `ross` object of type `Person` 7 | let ross: Person = { 8 | firstName: 'Ross', 9 | lastName: 'Geller' 10 | }; 11 | 12 | // update `lastName` property 13 | ross.lastName = 'Tribbiani'; 14 | 15 | // update `firstName` property 16 | // Error: Cannot assign to 'firstName' because it is a read-only property. 17 | ross.firstName = 'Joey'; -------------------------------------------------------------------------------- /declaration-files/ambient-declaration/.gitignore: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /declaration-files/ambient-declaration/program.ts: -------------------------------------------------------------------------------- 1 | console.log( version ); -------------------------------------------------------------------------------- /declaration-files/ambient-declaration/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "./program.ts" 4 | ], 5 | "compilerOptions": { 6 | "typeRoots": [ 7 | "./types" 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /declaration-files/ambient-declaration/types/common/functions.d.ts: -------------------------------------------------------------------------------- 1 | type GetFullName = ( p: Person ) => string; -------------------------------------------------------------------------------- /declaration-files/ambient-declaration/types/common/interfaces.d.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | firstName: string; 3 | lastName: string; 4 | age: number; 5 | } -------------------------------------------------------------------------------- /declaration-files/ambient-declaration/types/common/main.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | declare var version: string; -------------------------------------------------------------------------------- /declaration-files/ambient-declaration/types/common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "common", 3 | "version": "1.0.0", 4 | "typings": "main.d.ts" 5 | } -------------------------------------------------------------------------------- /declaration-files/custom-package/.gitignore: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /declaration-files/custom-package/human-test.ts: -------------------------------------------------------------------------------- 1 | import version, { Human, getFullName, Student } from 'human'; 2 | 3 | // var version: string 4 | console.log( version ); // 'v1.0.0' 5 | 6 | // const ross: Human 7 | const ross: Human = new Human( 'Ross', 'Geller', 1.85 ); 8 | 9 | // const className: string 10 | const className = Human.className; 11 | 12 | // const height: number 13 | const height = ross.getHeightInCm(); // 185 14 | 15 | // const rossName: string 16 | const rossName = getFullName( ross ); // Ross Geller 17 | 18 | // const monica: Student 19 | const monica: Student = { firstName: 'Monica', lastName: 'Geller', marks: 68 }; 20 | 21 | // const monicaName: string 22 | const monicaName = getFullName( monica ); // Monica Geller -------------------------------------------------------------------------------- /declaration-files/custom-package/local-declaration-test.ts: -------------------------------------------------------------------------------- 1 | import { Person } from './local-declaration'; 2 | 3 | const ross: Person = { 4 | firstName: 'Ross', 5 | lastName: 'Geller', 6 | age: 29 7 | }; -------------------------------------------------------------------------------- /declaration-files/custom-package/local-declaration.d.ts: -------------------------------------------------------------------------------- 1 | export interface Person { 2 | firstName: string; 3 | lastName: string; 4 | age: number; 5 | } 6 | -------------------------------------------------------------------------------- /declaration-files/custom-package/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "type-declaration-files", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@types/lodash": { 8 | "version": "4.14.157", 9 | "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.157.tgz", 10 | "integrity": "sha512-Ft5BNFmv2pHDgxV5JDsndOWTRJ+56zte0ZpYLowp03tW+K+t8u8YMOzAnpuqPgzX6WO1XpDIUm7u04M8vdDiVQ==", 11 | "dev": true 12 | }, 13 | "@types/node": { 14 | "version": "14.0.14", 15 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.14.tgz", 16 | "integrity": "sha512-syUgf67ZQpaJj01/tRTknkMNoBBLWJOBODF0Zm4NrXmiSuxjymFrxnTu1QVYRubhVkRcZLYZG8STTwJRdVm/WQ==", 17 | "dev": true 18 | }, 19 | "lodash": { 20 | "version": "4.17.15", 21 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 22 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /declaration-files/custom-package/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "type-declaration-files", 3 | "private": true, 4 | "version": "1.0.0", 5 | "devDependencies": { 6 | "@types/lodash": "^4.14.157", 7 | "@types/node": "^14.0.14" 8 | }, 9 | "dependencies": { 10 | "lodash": "^4.17.15" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /declaration-files/custom-package/packages/human/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "human", 3 | "version": "1.0.0", 4 | "main": "./human.js" 5 | } -------------------------------------------------------------------------------- /declaration-files/custom-package/packages/person/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "person", 3 | "version": "1.0.0", 4 | "main": "./person.js", 5 | "typings": "person.d.ts" 6 | } -------------------------------------------------------------------------------- /declaration-files/custom-package/packages/person/person.d.ts: -------------------------------------------------------------------------------- 1 | // export an interface 2 | export interface Student { 3 | firstName: string; 4 | lastName: string; 5 | marks: number; 6 | } 7 | 8 | // export a class 9 | export class Person { 10 | static className: string; 11 | 12 | public firstName: string; 13 | public lastName: string; 14 | public height: number; 15 | 16 | constructor(firstName: string, lastName: string, height: number); 17 | getHeightInCm(): number; 18 | } 19 | 20 | // export default value 21 | declare var version: string; 22 | export default version; 23 | 24 | // export a function 25 | export function getFullName(person: Person | Student): string; -------------------------------------------------------------------------------- /declaration-files/custom-package/person-test.ts: -------------------------------------------------------------------------------- 1 | import version, { Person, getFullName, Student } from 'person'; 2 | 3 | // var version: string 4 | console.log( version ); // 'v1.0.0' 5 | 6 | // const ross: Person 7 | const ross: Person = new Person( 'Ross', 'Geller', 1.85 ); 8 | 9 | // const className: string 10 | const className = Person.className; 11 | 12 | // const height: number 13 | const height = ross.getHeightInCm(); // 185 14 | 15 | // const rossName: string 16 | const rossName = getFullName( ross ); // Ross Geller 17 | 18 | // const monica: Student 19 | const monica: Student = { firstName: 'Monica', lastName: 'Geller', marks: 68 }; 20 | 21 | // const monicaName: string 22 | const monicaName = getFullName( monica ); // Monica Geller -------------------------------------------------------------------------------- /declaration-files/custom-package/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "./person-test.ts", 4 | "./human-test.ts", 5 | ], 6 | "compilerOptions": { 7 | "baseUrl": "./packages", 8 | "outDir": "dist", 9 | "typeRoots": [ 10 | "./node_modules/@types", 11 | "./types" 12 | ] 13 | } 14 | } -------------------------------------------------------------------------------- /declaration-files/custom-package/types/common/functions.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace common { 2 | type GetFullName = ( p: Person ) => string; 3 | } -------------------------------------------------------------------------------- /declaration-files/custom-package/types/common/interfaces.d.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | firstName: string; 3 | lastName: string; 4 | age: number; 5 | } -------------------------------------------------------------------------------- /declaration-files/custom-package/types/common/main.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | declare var version: string; -------------------------------------------------------------------------------- /declaration-files/custom-package/types/common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "common", 3 | "version": "1.0.0", 4 | "typings": "main.d.ts" 5 | } -------------------------------------------------------------------------------- /declaration-files/custom-package/types/human-types/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "human" { 2 | // export an interface 3 | export interface Student { 4 | firstName: string; 5 | lastName: string; 6 | marks: number; 7 | } 8 | 9 | // export a class 10 | export class Human { 11 | static className: string; 12 | 13 | public firstName: string; 14 | public lastName: string; 15 | public height: number; 16 | 17 | constructor(firstName: string, lastName: string, height: number); 18 | getHeightInCm(): number; 19 | } 20 | 21 | // export default value 22 | var version: string; 23 | export default version; 24 | } 25 | 26 | declare module "human" { 27 | // export a function 28 | export function getFullName(Human: Human | Student): string; 29 | } 30 | -------------------------------------------------------------------------------- /declaration-files/definitely-typed-lodash/.gitignore: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /declaration-files/definitely-typed-lodash/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "definitely-typed-lodash", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@types/lodash": { 8 | "version": "4.14.158", 9 | "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.158.tgz", 10 | "integrity": "sha512-InCEXJNTv/59yO4VSfuvNrZHt7eeNtWQEgnieIA+mIC+MOWM9arOWG2eQ8Vhk6NbOre6/BidiXhkZYeDY9U35w==", 11 | "dev": true 12 | }, 13 | "@types/node": { 14 | "version": "14.0.27", 15 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.27.tgz", 16 | "integrity": "sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g==", 17 | "dev": true 18 | }, 19 | "lodash": { 20 | "version": "4.17.19", 21 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", 22 | "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /declaration-files/definitely-typed-lodash/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "definitely-typed-lodash", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "program.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "@types/lodash": "^4.14.158", 14 | "@types/node": "^14.0.27" 15 | }, 16 | "dependencies": { 17 | "lodash": "^4.17.19" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /declaration-files/definitely-typed-lodash/program.ts: -------------------------------------------------------------------------------- 1 | import * as _ from 'lodash'; 2 | 3 | // typeof _.toUpper => any 4 | console.log( _.toUpper( true ) ); -------------------------------------------------------------------------------- /declaration-files/definitely-typed-lodash/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "./program.ts" 4 | ], 5 | "compilerOptions": { 6 | "lib": [ "ES2015" ], 7 | "typeRoots": [ 8 | "./node_modules/@types", 9 | "./types" 10 | ] 11 | } 12 | } -------------------------------------------------------------------------------- /declaration-files/definitely-typed-lodash/types/common/functions.d.ts: -------------------------------------------------------------------------------- 1 | type GetFullName = ( p: Person ) => string; -------------------------------------------------------------------------------- /declaration-files/definitely-typed-lodash/types/common/interfaces.d.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | firstName: string; 3 | lastName: string; 4 | age: number; 5 | } -------------------------------------------------------------------------------- /declaration-files/definitely-typed-lodash/types/common/main.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// -------------------------------------------------------------------------------- /declaration-files/definitely-typed-lodash/types/common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "common", 3 | "version": "1.0.0", 4 | "typings": "main.d.ts" 5 | } -------------------------------------------------------------------------------- /declaration-files/definitely-typed/.gitignore: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /declaration-files/definitely-typed/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "definitely-typed", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@types/node": { 8 | "version": "14.0.27", 9 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.27.tgz", 10 | "integrity": "sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g==", 11 | "dev": true 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /declaration-files/definitely-typed/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "definitely-typed", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "@types/node": "^14.0.27" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /declaration-files/definitely-typed/program.ts: -------------------------------------------------------------------------------- 1 | // declare a function of the type `GetFullName` 2 | const getPersonName: GetFullName = ( p: Person ) => { 3 | return `${ p.firstName } ${ p.lastName }`; 4 | } 5 | 6 | // create an object of the type `Person` 7 | const ross: Person = { 8 | firstName: 'Ross', 9 | lastName: 'Geller', 10 | age: 29, 11 | } 12 | 13 | // get name of the `Person` 14 | console.log( getPersonName( ross ) ); // Ross Geller -------------------------------------------------------------------------------- /declaration-files/definitely-typed/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "./program.ts" 4 | ], 5 | "compilerOptions": { 6 | "lib": [ "ES2015" ], 7 | "typeRoots": [ 8 | "./node_modules/@types", 9 | "./types" 10 | ] 11 | } 12 | } -------------------------------------------------------------------------------- /declaration-files/definitely-typed/types/common/functions.d.ts: -------------------------------------------------------------------------------- 1 | type GetFullName = ( p: Person ) => string; -------------------------------------------------------------------------------- /declaration-files/definitely-typed/types/common/interfaces.d.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | firstName: string; 3 | lastName: string; 4 | age: number; 5 | } -------------------------------------------------------------------------------- /declaration-files/definitely-typed/types/common/main.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// -------------------------------------------------------------------------------- /declaration-files/definitely-typed/types/common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "common", 3 | "version": "1.0.0", 4 | "typings": "main.d.ts" 5 | } -------------------------------------------------------------------------------- /declaration-files/extend-type-intro/.gitignore: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /declaration-files/extend-type-intro/program.ts: -------------------------------------------------------------------------------- 1 | // append global `Person` interface 2 | interface Person { 3 | email: string; 4 | } 5 | 6 | // append global `Number` interface 7 | interface Number { 8 | isEven(): boolean; 9 | } 10 | 11 | // create an object of type `Person` 12 | const ross: Person = { 13 | firstName: 'Ross', 14 | lastName: 'Geller', 15 | age: 29, 16 | email: 'ross@geller.com' 17 | } 18 | 19 | // (method) Number.isEven(): boolean 20 | const isAgeEven = ross.age.isEven(); 21 | 22 | // const isAgeEven: boolean 23 | console.log( 'isAgeEven', isAgeEven ); -------------------------------------------------------------------------------- /declaration-files/extend-type-intro/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "./program.ts" 4 | ], 5 | "compilerOptions": { 6 | "typeRoots": [ 7 | "./types" 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /declaration-files/extend-type-intro/types/common/functions.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace common { 2 | type GetFullName = ( p: Person ) => string; 3 | } -------------------------------------------------------------------------------- /declaration-files/extend-type-intro/types/common/interfaces.d.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | firstName: string; 3 | lastName: string; 4 | age: number; 5 | } -------------------------------------------------------------------------------- /declaration-files/extend-type-intro/types/common/main.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// -------------------------------------------------------------------------------- /declaration-files/extend-type-intro/types/common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "common", 3 | "version": "1.0.0", 4 | "typings": "main.d.ts" 5 | } -------------------------------------------------------------------------------- /declaration-files/extend-type-module-intro-fix/.gitignore: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /declaration-files/extend-type-module-intro-fix/.gitignore copy: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /declaration-files/extend-type-module-intro-fix/program.ts: -------------------------------------------------------------------------------- 1 | declare global { 2 | // append global `Person` interface 3 | interface Person { 4 | email: string; 5 | } 6 | } 7 | 8 | declare global { 9 | // append global `Number` interface 10 | interface Number { 11 | isEven(): boolean; 12 | } 13 | 14 | // declare global `version` 15 | var version: string; 16 | } 17 | 18 | // create an object of type `Person` 19 | const ross: Person = { 20 | firstName: 'Ross', 21 | lastName: 'Geller', 22 | age: 29, 23 | email: 'ross@geller.com' 24 | } 25 | 26 | // (method) Number.isEven(): boolean 27 | const isAgeEven = ross.age.isEven(); 28 | 29 | // const isAgeEven: boolean 30 | console.log( 'isAgeEven', isAgeEven ); 31 | 32 | // (make a module) 33 | export {} -------------------------------------------------------------------------------- /declaration-files/extend-type-module-intro-fix/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "./program.ts" 4 | ], 5 | "compilerOptions": { 6 | "typeRoots": [ 7 | "./types" 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /declaration-files/extend-type-module-intro-fix/types/common/functions.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace common { 2 | type GetFullName = ( p: Person ) => string; 3 | } -------------------------------------------------------------------------------- /declaration-files/extend-type-module-intro-fix/types/common/interfaces.d.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | firstName: string; 3 | lastName: string; 4 | age: number; 5 | } -------------------------------------------------------------------------------- /declaration-files/extend-type-module-intro-fix/types/common/main.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// -------------------------------------------------------------------------------- /declaration-files/extend-type-module-intro-fix/types/common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "common", 3 | "version": "1.0.0", 4 | "typings": "main.d.ts" 5 | } -------------------------------------------------------------------------------- /declaration-files/extend-type-module-intro/.gitignore: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /declaration-files/extend-type-module-intro/.gitignore copy: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /declaration-files/extend-type-module-intro/program.ts: -------------------------------------------------------------------------------- 1 | // append global `Person` interface 2 | interface Person { 3 | email: string; 4 | } 5 | 6 | // append global `Number` interface 7 | interface Number { 8 | isEven(): boolean; 9 | } 10 | 11 | // create an object of type `Person` 12 | const ross: Person = { 13 | firstName: 'Ross', 14 | lastName: 'Geller', 15 | age: 29, 16 | email: 'ross@geller.com' 17 | } 18 | 19 | // (method) Number.isEven(): boolean 20 | const isAgeEven = ross.age.isEven(); 21 | 22 | // const isAgeEven: boolean 23 | console.log( 'isAgeEven', isAgeEven ); 24 | 25 | // (make a module) 26 | export {} -------------------------------------------------------------------------------- /declaration-files/extend-type-module-intro/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "./program.ts" 4 | ], 5 | "compilerOptions": { 6 | "typeRoots": [ 7 | "./types" 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /declaration-files/extend-type-module-intro/types/common/functions.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace common { 2 | type GetFullName = ( p: Person ) => string; 3 | } -------------------------------------------------------------------------------- /declaration-files/extend-type-module-intro/types/common/interfaces.d.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | firstName: string; 3 | lastName: string; 4 | age: number; 5 | } -------------------------------------------------------------------------------- /declaration-files/extend-type-module-intro/types/common/main.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// -------------------------------------------------------------------------------- /declaration-files/extend-type-module-intro/types/common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "common", 3 | "version": "1.0.0", 4 | "typings": "main.d.ts" 5 | } -------------------------------------------------------------------------------- /declaration-files/intro/.gitignore: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /declaration-files/intro/global-type-promise-peek.ts: -------------------------------------------------------------------------------- 1 | const p = new Promise(); -------------------------------------------------------------------------------- /declaration-files/intro/program.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | const ross: Person = { 9 | firstName: 'Ross', 10 | lastName: 'Geller', 11 | } -------------------------------------------------------------------------------- /declaration-files/intro/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "./program.ts" 4 | ], 5 | "compilerOptions": { 6 | "typeRoots": [ 7 | "./types" 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /declaration-files/intro/types/common/main.d.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | firstName: string; 3 | lastName: string; 4 | age: number; 5 | } -------------------------------------------------------------------------------- /declaration-files/intro/types/common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "common", 3 | "version": "1.0.0", 4 | "typings": "main.d.ts" 5 | } -------------------------------------------------------------------------------- /declaration-files/modularity/.gitignore: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /declaration-files/modularity/program.ts: -------------------------------------------------------------------------------- 1 | // declare a function of the type `GetFullName` 2 | const getPersonName: GetFullName = ( p: Person ) => { 3 | return `${ p.firstName } ${ p.lastName }`; 4 | } 5 | 6 | // create an object of the type `Person` 7 | const ross: Person = { 8 | firstName: 'Ross', 9 | lastName: 'Geller', 10 | age: 29, 11 | } 12 | 13 | // get name of the `Person` 14 | console.log( getPersonName( ross ) ); // Ross Geller -------------------------------------------------------------------------------- /declaration-files/modularity/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "./program.ts" 4 | ], 5 | "compilerOptions": { 6 | "typeRoots": [ 7 | "./types" 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /declaration-files/modularity/types/common/functions.d.ts: -------------------------------------------------------------------------------- 1 | type GetFullName = ( p: Person ) => string; -------------------------------------------------------------------------------- /declaration-files/modularity/types/common/interfaces.d.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | firstName: string; 3 | lastName: string; 4 | age: number; 5 | } -------------------------------------------------------------------------------- /declaration-files/modularity/types/common/main.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// -------------------------------------------------------------------------------- /declaration-files/modularity/types/common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "common", 3 | "version": "1.0.0", 4 | "typings": "main.d.ts" 5 | } -------------------------------------------------------------------------------- /declaration-files/namespacing/.gitignore: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /declaration-files/namespacing/program.ts: -------------------------------------------------------------------------------- 1 | // declare a function of the type `GetFullName` 2 | const getPersonName: common.GetFullName = ( 3 | p: common.Person 4 | ) => { 5 | return `${ p.firstName } ${ p.lastName }`; 6 | } 7 | 8 | // create an object of the type `Person` 9 | const ross: common.Person = { 10 | firstName: 'Ross', 11 | lastName: 'Geller', 12 | age: 29, 13 | } 14 | 15 | // get name of the `Person` 16 | console.log( getPersonName( ross ) ); // Ross Geller -------------------------------------------------------------------------------- /declaration-files/namespacing/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "./program.ts" 4 | ], 5 | "compilerOptions": { 6 | "typeRoots": [ 7 | "./types" 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /declaration-files/namespacing/types/common/functions.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace common { 2 | type GetFullName = ( p: Person ) => string; 3 | } -------------------------------------------------------------------------------- /declaration-files/namespacing/types/common/interfaces.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace common { 2 | interface Person { 3 | firstName: string; 4 | lastName: string; 5 | age: number; 6 | } 7 | } -------------------------------------------------------------------------------- /declaration-files/namespacing/types/common/main.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// -------------------------------------------------------------------------------- /declaration-files/namespacing/types/common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "common", 3 | "version": "1.0.0", 4 | "typings": "main.d.ts" 5 | } -------------------------------------------------------------------------------- /decorators/.gitignore: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /decorators/accessor-decorator.ts: -------------------------------------------------------------------------------- 1 | // convert accessor to uppercase 2 | function uppercase( target, name, desc ) { 3 | return { 4 | enumerable: false, 5 | configurable: false, 6 | get: function () { 7 | return desc.get.call( this ).toUpperCase(); 8 | }, 9 | set: function ( name ) { 10 | desc.set.call( this, name.split(' ') ); 11 | } 12 | }; 13 | } 14 | 15 | class Person { 16 | constructor( 17 | public fname: string, public lname: string, 18 | ) {} 19 | 20 | @uppercase 21 | get fullname(): string { 22 | return this.fname + ' ' + this.lname; 23 | } 24 | 25 | set fullname( [ fname, lname ] ) { 26 | this.fname = fname; 27 | this.lname = lname; 28 | } 29 | } 30 | 31 | var person = new Person( 'Ross', 'Geller' ); 32 | console.log( 'fullname ->', person.fullname ); 33 | console.log( 'person ->', person ); 34 | 35 | person.fullname = 'Chandler Bing'; 36 | console.log( 'fullname* ->', person.fullname ); 37 | console.log( 'person* ->', person ); -------------------------------------------------------------------------------- /decorators/class-decorator-extend.ts: -------------------------------------------------------------------------------- 1 | // `Ctor` type presents a constructor function 2 | interface Ctor { 3 | new (...args: any[] ): any; 4 | } 5 | 6 | // return a new class that extends incoming class 7 | function withInfo( ctor: T ): T { 8 | return class NewCtor extends ctor { 9 | info(): string { 10 | return `An instance of a "${ ctor.name }".`; 11 | } 12 | }; 13 | } 14 | 15 | @withInfo 16 | class Person { 17 | static version: string = 'v1.0.0'; 18 | 19 | fname: string; 20 | lname: string; 21 | 22 | constructor( fname: string, lname: string ) { 23 | this.fname = fname; 24 | this.lname = lname; 25 | } 26 | 27 | getFullName(): string { 28 | return this.fname + ' ' + this.lname; 29 | } 30 | } 31 | 32 | const person = new Person( 'Ross', 'Geller' ); 33 | console.log( 'version ->', Person.version ); 34 | console.log( 'fullname ->', person.getFullName() ); 35 | console.log( 'info ->', (person as any).info() ); -------------------------------------------------------------------------------- /decorators/class-decorator-factory.ts: -------------------------------------------------------------------------------- 1 | // decorator factory 2 | function version( version: string ) { 3 | return function( target: any ) { 4 | target.version = version; 5 | } 6 | } 7 | 8 | @version('v1.0.1') 9 | class Person { 10 | fname: string; 11 | lname: string; 12 | 13 | constructor( fname: string, lname: string ) { 14 | this.fname = fname; 15 | this.lname = lname; 16 | } 17 | 18 | getFullName(): string { 19 | return this.fname + ' ' + this.lname; 20 | } 21 | } 22 | 23 | // log class version 24 | console.log( 'version ->', (Person as any).version ); -------------------------------------------------------------------------------- /decorators/class-decorator.ts: -------------------------------------------------------------------------------- 1 | // lock decorator for classes 2 | function lock( ctor: Function ) { 3 | Object.freeze( ctor ); 4 | Object.freeze( ctor.prototype ); 5 | } 6 | 7 | @lock 8 | class Person { 9 | static version: string = 'v1.0.0'; 10 | 11 | fname: string; 12 | lname: string; 13 | 14 | constructor( fname: string, lname: string ) { 15 | this.fname = fname; 16 | this.lname = lname; 17 | } 18 | 19 | getFullName(): string { 20 | return this.fname + ' ' + this.lname; 21 | } 22 | } 23 | 24 | // add properties to class 25 | Person.version = 'v1.0.1'; 26 | // ❌ Error => TypeError: Cannot assign to read only property 'version' of function 'class Person' 27 | 28 | // add properties to class prototype 29 | Person.prototype.getFullName = null; 30 | // ❌ Error => TypeError: Cannot assign to read only property 'getFullName' of object '#' -------------------------------------------------------------------------------- /decorators/decoration-order.ts: -------------------------------------------------------------------------------- 1 | // decorator factory 2 | function factory( label: string ) { 3 | console.log( 'factory():', label ); 4 | return function( ...args: any[] ) { 5 | console.log( 'decorator():', label ); 6 | } 7 | } 8 | 9 | @factory('class') 10 | class Person { 11 | @factory('property-instance') name: string; 12 | @factory('property-static') static version: string; 13 | 14 | constructor( 15 | @factory('param-constructor') name: string 16 | ) { this.name = name } 17 | 18 | @factory('method-instance') 19 | getName( 20 | @factory('param-instance') prefix: string 21 | ) { return prefix + ' ' + this.name; } 22 | 23 | @factory('getter-instance') 24 | personName() { return this.name;} 25 | 26 | @factory('method-static') 27 | static getVersion( 28 | @factory('param-static') prefix: string 29 | ) { return prefix + '' + this.version; } 30 | 31 | @factory('getter-static') 32 | static personVersion() { return this.version;} 33 | } -------------------------------------------------------------------------------- /decorators/decorator-chaining.ts: -------------------------------------------------------------------------------- 1 | // decorator factory 2 | function decoratorFactory( label: string ) { 3 | console.log( 'factory():', label ); 4 | return function( ...args: any[] ) { 5 | console.log( 'decorator():', label ); 6 | } 7 | } 8 | 9 | // decorator 10 | function decorator( ...args: any[] ) { 11 | console.log( 'decorator():', 'param-B' ); 12 | } 13 | 14 | @decoratorFactory('class-A') 15 | @decoratorFactory('class-B') 16 | @decoratorFactory('class-C') 17 | class Person { 18 | constructor( 19 | @decoratorFactory('param-A') @decorator @decoratorFactory('param-C') public name: string 20 | ) {} 21 | } -------------------------------------------------------------------------------- /decorators/emit-decorator-metadata.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | 3 | // decorator function that does nothig 4 | function noop(...args: any[]) {} 5 | 6 | @noop 7 | class Person { 8 | constructor( 9 | public name: string, 10 | public age: number, 11 | ) {} 12 | 13 | getAge(): string { 14 | return this.age.toString(); 15 | } 16 | 17 | @noop 18 | getNameWithPrefix(prefix: string): string { 19 | const type = Reflect.getMetadata( 20 | 'design:type', this, 'getNameWithPrefix' 21 | ); console.log( 'type ->', type ); 22 | 23 | const paramtypes = Reflect.getMetadata( 24 | 'design:paramtypes', this, 'getNameWithPrefix' 25 | ); console.log( 'paramtypes ->', paramtypes ); 26 | 27 | const returntype = Reflect.getMetadata( 28 | 'design:returntype', this, 'getNameWithPrefix' 29 | ); console.log( 'returntype ->', returntype ); 30 | 31 | return prefix + ' ' + this.name; 32 | } 33 | } 34 | 35 | var person = new Person( 'Ross Geller', 29 ); 36 | person.getNameWithPrefix( 'Dr.' ); -------------------------------------------------------------------------------- /decorators/method-decorator.ts: -------------------------------------------------------------------------------- 1 | // make property readonly 2 | function readonly( target, name, desc ) { 3 | desc.writable = false; 4 | } 5 | 6 | // adds `v` prefix 7 | function prefix( target, name, desc ) { 8 | return { 9 | writable: false, enumerable: false, 10 | configurable: false, 11 | value: () => `v${ desc.value() }`, 12 | }; 13 | } 14 | 15 | class Person { 16 | constructor( 17 | public fname: string, public lname: string 18 | ) {} 19 | 20 | @readonly 21 | getFullName(): string { 22 | return this.fname + ' ' + this.lname; 23 | } 24 | 25 | @prefix 26 | static getVersion() { 27 | return '1.0.0'; 28 | } 29 | } 30 | 31 | // get version 32 | console.log( 'version ->', Person.getVersion() ); 33 | // ✅ v1.0.0 34 | 35 | // override `getFullName` method 36 | Person.prototype.getFullName = null; 37 | // ❌ TypeError: Cannot assign to read only property 'getFullName' of object '#' -------------------------------------------------------------------------------- /decorators/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "decorators", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "reflect-metadata": { 8 | "version": "0.1.13", 9 | "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", 10 | "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", 11 | "dev": true 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /decorators/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "decorators", 3 | "version": "1.0.0", 4 | "devDependencies": { 5 | "reflect-metadata": "^0.1.13" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /decorators/parameter-decorator.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | 3 | // save metadata of a parameter with its index 4 | function textCase( target, name, index ) { 5 | const tcase = index === 0 ? 'upper' : 'lower'; 6 | Reflect.defineMetadata( `case_${index}`, tcase, target, name ); 7 | } 8 | 9 | // get text case from metadata 10 | function getTextCase( target, name, index ) { 11 | return Reflect.getMetadata( `case_${index}`, target, name ); 12 | } 13 | 14 | class Person { 15 | public fname: string; 16 | public lname: string; 17 | 18 | constructor( 19 | @textCase fname: string, 20 | @textCase lname: string 21 | ) { 22 | this.fname = fname; 23 | this.lname = lname; 24 | } 25 | 26 | get fullname(): string { 27 | const fnameCase = getTextCase( Person, undefined, 0 ); 28 | const lnameCase = getTextCase( Person, undefined, 1 ); 29 | 30 | const fname = 'upper' === fnameCase ? this.fname.toUpperCase() : this.fname.toLowerCase(); 31 | const lname = 'upper' === lnameCase ? this.lname.toUpperCase() : this.lname.toLowerCase(); 32 | 33 | return fname + ' ' + lname; 34 | } 35 | } 36 | 37 | var person = new Person( 'Ross', 'Geller' ); 38 | console.log( person.fullname ); -------------------------------------------------------------------------------- /decorators/property-decorator-reflect.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | 3 | // get text case from metadata 4 | function getTextCase( target, name ) { 5 | return Reflect.getMetadata( 'case', target, name ); 6 | } 7 | 8 | class Person { 9 | @Reflect.metadata( 'case', 'upper' ) 10 | public fname: string; 11 | 12 | @Reflect.metadata( 'case', 'lower' ) 13 | public lname: string; 14 | 15 | constructor( fname: string, lname: string ) { 16 | this.fname = fname; 17 | this.lname = lname; 18 | } 19 | 20 | get fullname(): string { 21 | const fnameCase = getTextCase( this, 'fname' ); 22 | const lnameCase = getTextCase( this, 'lname' ); 23 | 24 | const fname = 'upper' === fnameCase ? this.fname.toUpperCase() : this.fname.toLowerCase(); 25 | const lname = 'upper' === lnameCase ? this.lname.toUpperCase() : this.lname.toLowerCase(); 26 | 27 | return fname + ' ' + lname; 28 | } 29 | } 30 | 31 | var person = new Person( 'Ross', 'Geller' ); 32 | console.log( person.fullname ); -------------------------------------------------------------------------------- /decorators/property-decorator.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | 3 | // decorator to save metadata of a property 4 | function textCase( target, name ) { 5 | const tcase = name === 'fname' ? 'upper' : 'lower'; 6 | Reflect.defineMetadata( 'case', tcase, target, name ); 7 | } 8 | 9 | // get text case from metadata 10 | function getTextCase( target, name ) { 11 | return Reflect.getMetadata( 'case', target, name ); 12 | } 13 | 14 | class Person { 15 | @textCase 16 | public fname: string; 17 | 18 | @textCase 19 | public lname: string; 20 | 21 | constructor( fname: string, lname: string ) { 22 | this.fname = fname; 23 | this.lname = lname; 24 | } 25 | 26 | get fullname(): string { 27 | const fnameCase = getTextCase( this, 'fname' ); 28 | const lnameCase = getTextCase( this, 'lname' ); 29 | 30 | const fname = 'upper' === fnameCase ? this.fname.toUpperCase() : this.fname.toLowerCase(); 31 | const lname = 'upper' === lnameCase ? this.lname.toUpperCase() : this.lname.toLowerCase(); 32 | 33 | return fname + ' ' + lname; 34 | } 35 | } 36 | 37 | var person = new Person( 'Ross', 'Geller' ); 38 | console.log( person.fullname ); -------------------------------------------------------------------------------- /decorators/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "class-decorator.ts" 4 | ], 5 | "compilerOptions": { 6 | "target": "ES6", 7 | "module": "CommonJS", 8 | "experimentalDecorators": true, 9 | "emitDecoratorMetadata": true, 10 | "removeComments": true, 11 | "alwaysStrict": true 12 | } 13 | } -------------------------------------------------------------------------------- /enums/.gitignore: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /enums/enum-as-type.ts: -------------------------------------------------------------------------------- 1 | // define an enum 2 | enum Speed { 3 | SLOW = 1, 4 | MEDIUM, 5 | FAST 6 | } 7 | 8 | // define `Racer` interface 9 | interface Racer { 10 | name: string; 11 | speed: Speed; // `speed` value has `Speed` enum type 12 | } 13 | 14 | // create a racer object 15 | let ross: Racer = { 16 | name: 'Ross Geller', 17 | speed: Speed.MEDIUM, 18 | }; 19 | 20 | // log `ross` object 21 | console.log( 'ross =>', ross ); -------------------------------------------------------------------------------- /enums/enum-computed-member.ts: -------------------------------------------------------------------------------- 1 | // define an enum 2 | enum Speed { 3 | SLOW = 1, // constant member 4 | MEDIUM, // constant member 5 | FAST = parseInt( "3" ), // computed member 6 | } 7 | 8 | // log `Speed` enum 9 | console.log( 'Speed =>', Speed ); 10 | 11 | // define `Racer` interface 12 | interface Racer { 13 | name: string; 14 | speed: Speed; // enum type 15 | } 16 | 17 | // create a racer object 18 | let ross: Racer = { 19 | name: 'Ross Geller', 20 | speed: Speed.FAST, // computed enum value 21 | }; 22 | 23 | // log `ross` object 24 | console.log( 'ross =>', ross ); -------------------------------------------------------------------------------- /enums/enum-const.ts: -------------------------------------------------------------------------------- 1 | // define a constant enum 2 | const enum Speed { 3 | SLOW = "slow", 4 | MEDIUM = "medium", 5 | FAST = "fast" 6 | } 7 | 8 | // define a simple object 9 | let racer = { 10 | name: 'Ross Geller', 11 | speed: Speed.MEDIUM 12 | }; 13 | 14 | // log `racer` object 15 | console.log( 'racer =>', racer ); 16 | 17 | // Error: 'const' enums can only be used in property or index access expressions or the right hand side of an import declaration or export assignment or type query. 18 | // console.log( "Speed => ", Speed ); -------------------------------------------------------------------------------- /enums/enum-js-object.ts: -------------------------------------------------------------------------------- 1 | // define an enum 2 | enum Speed { 3 | SLOW, 4 | MEDIUM, 5 | FAST 6 | } 7 | 8 | // log `Speed` enum 9 | console.log( 'Speed =>', Speed ); -------------------------------------------------------------------------------- /enums/enum-member-as-type.ts: -------------------------------------------------------------------------------- 1 | // define an enum 2 | enum Speed { 3 | SLOW = 1, 4 | MEDIUM, 5 | FAST 6 | } 7 | 8 | // define `Racer` interface 9 | interface Racer { 10 | name: string; 11 | speed: Speed.MEDIUM; // can only be `Speed.MEDIUM` 12 | } 13 | 14 | // create a racer object 15 | let ross: Racer = { 16 | name: 'Ross Geller', 17 | speed: Speed.MEDIUM, 18 | }; 19 | 20 | // Error: Type 'Speed.FAST' is not assignable to type 'Speed.MEDIUM'. 21 | ross.speed = Speed.FAST; -------------------------------------------------------------------------------- /enums/enum-member-values.ts: -------------------------------------------------------------------------------- 1 | // define an enum 2 | enum Speed { 3 | SLOW = 30, 4 | MEDIUM = SLOW + 30, 5 | FAST = MEDIUM + 40 6 | } 7 | 8 | // log `Speed` enum 9 | console.log( 'Speed =>', Speed ); 10 | 11 | // define `Racer` interface 12 | interface Racer { 13 | name: string; 14 | speed: Speed; 15 | } 16 | 17 | // create a racer object 18 | let ross: Racer = { 19 | name: 'Ross Geller', 20 | speed: Speed.FAST, 21 | }; 22 | 23 | // log `ross` object 24 | console.log( 'ross =>', ross ); -------------------------------------------------------------------------------- /enums/enum-non-const.ts: -------------------------------------------------------------------------------- 1 | // define a non-constant enum 2 | enum Speed { 3 | SLOW = "slow", 4 | MEDIUM = "medium", 5 | FAST = "fast" 6 | } 7 | 8 | // define a simple object 9 | let racer = { 10 | name: 'Ross Geller', 11 | speed: Speed.MEDIUM, // enum value 12 | }; 13 | 14 | // log `racer` object 15 | console.log( 'racer =>', racer ); -------------------------------------------------------------------------------- /enums/enum-permission.ts: -------------------------------------------------------------------------------- 1 | // define an enum 2 | enum Permission { 3 | EXECUTE = 0o1, // octal: 1 4 | WRITE = 0o2, // octal: 2 5 | WRITE_EXECUTE = EXECUTE | WRITE, // octal: 3 6 | READ = 0o4, // octal: 4 7 | READ_EXECUTE = READ | EXECUTE, // octal: 5 8 | READ_WRITE = READ | WRITE, // octal: 6 9 | READ_WRITE_EXECUTE = READ | WRITE | EXECUTE, // octal: 7 10 | } 11 | 12 | // log `Permission` enum 13 | console.log( Permission ); -------------------------------------------------------------------------------- /enums/enum-reverse-mapping.ts: -------------------------------------------------------------------------------- 1 | // define an enum 2 | enum Speed { 3 | SLOW = 30, 4 | MEDIUM = 60, 5 | FAST = 100 6 | } 7 | 8 | // my speed value 9 | let mySpeed = Speed.MEDIUM; // 60 10 | 11 | // log speed names 12 | console.log( 'Speed[mySpeed] =>', Speed[ mySpeed ] ); 13 | console.log( 'Speed[100] =>', Speed[ 100 ] ); -------------------------------------------------------------------------------- /enums/enum-string.ts: -------------------------------------------------------------------------------- 1 | // define an enum 2 | enum Speed { 3 | SLOW = "slow", 4 | MEDIUM = "medium", 5 | FAST = "fast" 6 | } 7 | 8 | // print enum object 9 | console.log( 'Speed =>', Speed ); 10 | 11 | // use member value 12 | console.log( 'Speed.MEDIUM =>', Speed.MEDIUM ); -------------------------------------------------------------------------------- /enums/enum.ts: -------------------------------------------------------------------------------- 1 | // define an enum 2 | enum Speed { 3 | SLOW = 1, 4 | MEDIUM, 5 | FAST 6 | } 7 | 8 | // log a enum values 9 | console.log( 'Speed.SLOW =>', Speed.SLOW ); 10 | console.log( 'Speed.MEDIUM =>', Speed.MEDIUM ); 11 | console.log( 'Speed.FAST =>', Speed.FAST ); -------------------------------------------------------------------------------- /functions/currying-concrete-type.ts: -------------------------------------------------------------------------------- 1 | // declare `_add` and `_subtract` function variables 2 | let _add: (a: string, b: string) => string; 3 | let _subtract: (a: number, b: number) => number; 4 | 5 | // assign function values 6 | _add = ( a: string, b: string ): string => a + b; 7 | _subtract = ( a: number, b: number ): number => a - b; 8 | 9 | // declare `getOperation` function 10 | let getOperation = ( operation: string ): (a: number, b: number) => number => { 11 | if( operation === 'add' ) { 12 | return _add; 13 | } else { 14 | return _subtract; 15 | } 16 | } 17 | 18 | // perform `add` operation 19 | console.log( getOperation( 'add' )( 1, "10" ) ); -------------------------------------------------------------------------------- /functions/currying-native-type.ts: -------------------------------------------------------------------------------- 1 | // declare `_add` and `_subtract` function variables 2 | let _add: (a: number, b: number) => number; 3 | let _subtract: (a: number, b: number) => number; 4 | 5 | // assign function values 6 | _add = ( a: number, b: number ): number => a + b; 7 | _subtract = ( a: number, b: number ): number => a - b; 8 | 9 | // declare `getOperation` function 10 | let getOperation = ( operation: string ): Function => { 11 | if( operation === 'add' ) { 12 | return _add; 13 | } else { 14 | return _subtract; 15 | } 16 | } 17 | 18 | // perform `add` operation 19 | console.log( getOperation( 'add' )( 1, "10" ) ); 20 | 21 | // is a function instance of `Function` 22 | console.log( getOperation( 'add' ) instanceof Function ); -------------------------------------------------------------------------------- /functions/function-alias-type.ts: -------------------------------------------------------------------------------- 1 | // declare `ArithmeticFunc` type-alias 2 | type ArithmeticFunc = (a: number, b: number) => number; 3 | 4 | // assign function values 5 | const _add: ArithmeticFunc = ( a: number, b: number ): number => a + b; 6 | const _subtract: ArithmeticFunc = ( a: number, b: number ): number => a - b; 7 | 8 | // declare `getOperation` function 9 | let getOperation = ( operation: string ): ArithmeticFunc => { 10 | if( operation === 'add' ) { 11 | return _add; 12 | } else { 13 | return _subtract; 14 | } 15 | } 16 | 17 | // perform `add` operation 18 | console.log( getOperation( 'add' )( 1, "10" ) ); -------------------------------------------------------------------------------- /functions/function-arrow-expression.ts: -------------------------------------------------------------------------------- 1 | // declare a function (using function expression) 2 | const sum = ( a: number, b: number ): number => a + b; 3 | 4 | // print sum of `1` and `2 5 | console.log( 'sum( 1, 2 ) =>', sum( 1, 2 ) ); 6 | 7 | // operate on the return value 8 | console.log( 'sum( 1, 2 ) + 7 =>', sum( 1, 2 ) + 7 ); 9 | console.log( 'sum( 1, 2 ).toFixed(2) =>', sum( 1, 2 ).toFixed( 2 ) ); -------------------------------------------------------------------------------- /functions/function-declaration.ts: -------------------------------------------------------------------------------- 1 | // declare a function 2 | function sum( a: number, b: number ): number { 3 | return a + b; 4 | } 5 | 6 | // print sum of `1` and `2 7 | console.log( 'sum( 1, 2 ) =>', sum( 1, 2 ) ); 8 | 9 | // operate on the return value 10 | console.log( 'sum( 1, 2 ) + 7 =>', sum( 1, 2 ) + 7 ); 11 | 12 | // invalid or unsafe operations 13 | console.log( 'sum( 1 ) =>', sum( 1 ) ); 14 | console.log( 'sum( "1", 2 ) =>', sum( "1", 2 ) ); 15 | console.log( 'sum( "1", 2 ) + 7 =>', sum( "1", 2 ) + 7 ); 16 | console.log( 'sum( "1", 2 ).split("") =>', sum( 1, 2 ).split("") ); 17 | console.log( 'sum( undefined, 2 ) =>', sum( undefined, 2 ) ); 18 | console.log( 'sum() =>', sum() ); 19 | console.log( 'sum( 1, 2, 3 ) =>', sum( 1, 2, 3 ) ); 20 | console.log( 'sum( 1, 2, 3 ) + 7 =>', sum( 1, 2, 3 ) + 7 ); -------------------------------------------------------------------------------- /functions/function-default-parameter-values.ts: -------------------------------------------------------------------------------- 1 | // declare a function 2 | let printPerson = ( name: string, age: number, canDrive: boolean = true ) => { 3 | if( canDrive ) { 4 | return `${ name } of age ${ age } can drive.`; 5 | } else { 6 | return `${ name } of age ${ age } can not drive.`; 7 | } 8 | }; 9 | 10 | console.log( printPerson( "Ross Geller", 28 ) ); // no errors 11 | console.log( printPerson( "Monica Geller", 26, false ) ); -------------------------------------------------------------------------------- /functions/function-expression.ts: -------------------------------------------------------------------------------- 1 | // declare a function (using function expression) 2 | const sum = function( a: number, b: number ): number { 3 | return a + b; 4 | } 5 | 6 | // print sum of `1` and `2 7 | console.log( 'sum( 1, 2 ) =>', sum( 1, 2 ) ); 8 | 9 | // operate on the return value 10 | console.log( 'sum( 1, 2 ) + 7 =>', sum( 1, 2 ) + 7 ); 11 | console.log( 'sum( 1, 2 ).toFixed(2) =>', sum( 1, 2 ).toFixed( 2 ) ); -------------------------------------------------------------------------------- /functions/function-optional-parameters.ts: -------------------------------------------------------------------------------- 1 | // declare a function with optional parameters 2 | let printPerson = ( name: string, age: number, canDrive?: boolean ) => { 3 | if( canDrive ) { 4 | return `${ name } of age ${ age } can drive.`; 5 | } else { 6 | return `${ name } of age ${ age } can not drive.`; 7 | } 8 | }; 9 | 10 | console.log( printPerson( "Ross Geller", 28 ) ); // no errors 11 | console.log( printPerson( "Monica Geller", 26, true ) ); -------------------------------------------------------------------------------- /functions/function-overloading.ts: -------------------------------------------------------------------------------- 1 | function concatenate( a: number, b: number ): number; 2 | function concatenate( a: string, b: string ): string; 3 | function concatenate( a: string, b: number ): null; 4 | function concatenate( a: number, b: string ): null; 5 | function concatenate( a: any, b: any ): any { 6 | if( typeof a === 'string' && typeof b === 'string' ) { 7 | return `${ a }-${ b }`; 8 | } else if ( typeof a === 'number' && typeof b === 'number' ) { 9 | return a + b; 10 | } else { 11 | return null; 12 | } 13 | } 14 | 15 | // when all arguments are `string` 16 | console.log( concatenate( 'John', 'Doe' ).toUpperCase() ); 17 | 18 | // when all arguments are `number` 19 | console.log( concatenate( 1.5, 2.12 ).toFixed( 1 ) ); 20 | 21 | // check for mixed arguments types 22 | console.log( concatenate( 1.5, '2.12' ).toFixed( 1 ) ); -------------------------------------------------------------------------------- /functions/function-rest-parameters.ts: -------------------------------------------------------------------------------- 1 | // declare a variadic function 2 | let printStudent = ( name: string, ...books: string[] ) => { 3 | return `${ name } likes ${ books.join( ', ' ) }.`; 4 | }; 5 | 6 | console.log( printStudent( 'Ross', 'Math', 'Science', 'Geology' ) ); -------------------------------------------------------------------------------- /functions/function-spread-operator.ts: -------------------------------------------------------------------------------- 1 | // declare a variadic function 2 | let printThings = ( name: string, ...things: any[] ) => { 3 | return `${ name } likes ${ things.join( ', ' ) }.`; 4 | }; 5 | 6 | // define `things` array 7 | let things: any[] = [ 'Car', 123, true ]; 8 | 9 | // works but not idead 10 | console.log( printThings( 'Ross', things[0], things[1] ) ); 11 | 12 | // ideal approach using `spread` operator 13 | console.log( printThings( 'Ross', ...things ) ); -------------------------------------------------------------------------------- /functions/function-type-with-alias.ts: -------------------------------------------------------------------------------- 1 | // declare type alias 2 | type ArithmeticFunction = ( a: number, b: number ) => number; 3 | 4 | // declare `add` function 5 | let add: ArithmeticFunction = ( a: number, b: number ): number => { 6 | return a + b; 7 | } 8 | 9 | // declare `subtract` function 10 | let subtract: ArithmeticFunction = ( a: number, b: number ): number => { 11 | return a - b; 12 | } 13 | 14 | // declare `calculate` function 15 | let getOperation = ( operation: string ): ArithmeticFunction => { 16 | return ( operation == 'add' ) ? add : subtract; 17 | } 18 | 19 | // get operation function 20 | let addOperation: ArithmeticFunction = getOperation( 'add' ); 21 | 22 | // call operation function 23 | console.log( addOperation( 1, 2 ) ); -------------------------------------------------------------------------------- /functions/function-typed-expression.ts: -------------------------------------------------------------------------------- 1 | // declare a variable of type function 2 | let sum: ( a: number, b: number ) => number; 3 | 4 | // assign a (function) value to `sum` 5 | sum = ( a: number, b: number ): number => a + b; // redundant 6 | sum = ( a, b ) => a + b; 7 | 8 | // print sum of `1` and `2 9 | console.log( 'sum( 1, 2 ) =>', sum( 1, 2 ) ); 10 | 11 | // operate on the return value 12 | console.log( 'sum( 1, 2 ) + 7 =>', sum( 1, 2 ) + 7 ); 13 | console.log( 'sum( 1, 2 ).toFixed(2) =>', sum( 1, 2 ).toFixed( 2 ) ); -------------------------------------------------------------------------------- /functions/vanilla-function.js: -------------------------------------------------------------------------------- 1 | // declare a function 2 | function sum( a, b ) { 3 | return a + b; 4 | } 5 | 6 | // print sum of `1` and `2 7 | console.log( 'sum( 1, 2 ) =>', sum( 1, 2 ) ); 8 | 9 | // operate on the return value 10 | console.log( 'sum( 1, 2 ) + 7 =>', sum( 1, 2 ) + 7 ); 11 | 12 | // invalid or unsafe operations 13 | console.log( 'sum( 1 ) =>', sum( 1 ) ); 14 | console.log( 'sum( "1", 2 ) =>', sum( "1", 2 ) ); 15 | console.log( 'sum( "1", 2 ) + 7 =>', sum( "1", 2 ) + 7 ); 16 | console.log( 'sum( "1", 2 ).split("") =>', sum( 1, 2 ).split("") ); 17 | console.log( 'sum( undefined, 2 ) =>', sum( undefined, 2 ) ); 18 | console.log( 'sum() =>', sum() ); 19 | 20 | // not appropriate but works 21 | console.log( 'sum( 1, 2, 3 ) =>', sum( 1, 2, 3 ) ); 22 | console.log( 'sum( 1, 2, 3 ) + 7 =>', sum( 1, 2, 3 ) + 7 ); -------------------------------------------------------------------------------- /generics/.gitignore: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /generics/generic-class-factory.ts: -------------------------------------------------------------------------------- 1 | // create constructor function type alias 2 | type Ctor = new ( ...args: any[] ) => U; 3 | 4 | // factory function 5 | function simpleFactory( 6 | ctor: Ctor, 7 | ...args: any[] 8 | ): T { 9 | return new ctor( ...args ); 10 | } 11 | 12 | class Person { 13 | constructor( 14 | public firstName: string, 15 | public lastName: string 16 | ){} 17 | } 18 | 19 | class Teacher { 20 | constructor( 21 | public firstName: string, 22 | public lastName: string, 23 | public age: number 24 | ){} 25 | } 26 | 27 | // var ross: Person 28 | var ross = simpleFactory( Person, 'Ross', 'Geller' ); 29 | console.log( 'ross =>', ross ); 30 | 31 | // var monica: Teacher 32 | var monica = simpleFactory( Teacher, 'Mon', 'Geller', 31 ); 33 | console.log( 'monica =>', monica ); -------------------------------------------------------------------------------- /generics/generic-class.ts: -------------------------------------------------------------------------------- 1 | // declare a generic class 2 | class Items { 3 | public items: U[]; 4 | 5 | constructor( ...values: U[] ) { 6 | this.items = values; 7 | } 8 | } 9 | 10 | // generic class extends another generic class 11 | class Collection extends Items { 12 | getFirstItem(): T { 13 | return this.items[ 0 ]; 14 | } 15 | } 16 | 17 | // a collection of `string` items 18 | var letters = new Collection( 1, 'b', 'c' ); 19 | 20 | // var item: string 21 | var item = letters.getFirstItem(); 22 | console.log( 'item =>', item.toUpperCase() ); -------------------------------------------------------------------------------- /generics/generic-constraints-function.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | fn: string; ln: string; 3 | } 4 | 5 | interface Student { 6 | fn: string; ln: string; age: number; 7 | } 8 | 9 | interface Teacher { 10 | name: string; age: number; 11 | } 12 | 13 | // a generic function with constraints 14 | function getFullName( p: T ): string { 15 | return `${ p.fn } ${ p.ln }`; 16 | } 17 | 18 | // create some objects 19 | var ross: Person = { fn: 'Ross', ln: 'Geller' }; 20 | var monica: Student = { fn: 'Mon', ln: 'Geller', age: 28 }; 21 | var rachel = { fn: 'Rachel', ln: 'Green', marks: 42 }; 22 | var joey: Teacher = { name: 'Joey Tribbiani', age: 32 }; 23 | 24 | console.log( 'Ross =>', getFullName( ross ) ); 25 | console.log( 'Monica =>', getFullName( monica ) ); 26 | console.log( 'Rachel =>', getFullName( rachel ) ); 27 | 28 | // Error: Argument of type 'Teacher' is not assignable to parameter of type 'Person'. 29 | // Type 'Teacher' is missing the following properties from type 'Person': firstName, lastName. 30 | console.log( 'Joey =>', getFullName( joey ) ); -------------------------------------------------------------------------------- /generics/generic-constraints-union-with-union.ts: -------------------------------------------------------------------------------- 1 | // declare a generic function with constraints 2 | function getValue( arg: T ): T { 3 | return arg; 4 | }; 5 | 6 | // function getValue<"hello">(value: "hello"): "hello" 7 | // var value1: "hello" 8 | var value1 = getValue( 'hello' ); 9 | 10 | // function getValue(value: string): string 11 | // var value2: string 12 | var value2 = getValue( 'hello' as string ); 13 | 14 | // function getValue(value: string | number): string | number 15 | // var value3: string | number 16 | var value3 = getValue( 'hello' as string | number ); 17 | 18 | // function getValue(value: any): any 19 | // var value4: any 20 | var value4 = getValue( 'hello' as any ); 21 | 22 | // Error: Argument of type 'symbol' is not assignable to parameter of type 'string | number | boolean'. 23 | var value5 = getValue( Symbol() as symbol ); 24 | 25 | // Error: Argument of type 'string | number | symbol' is not assignable to parameter of type 'string | number | boolean'. 26 | // Type 'symbol' is not assignable to type 'string | number | boolean'. 27 | var value6 = getValue( 'hello' as string | number | symbol ); -------------------------------------------------------------------------------- /generics/generic-constraints-union.ts: -------------------------------------------------------------------------------- 1 | var car = { name: 'Audi', model: 'R8' }; 2 | var fruit = { type: 'Mango', color: 'Red', weight: 6 }; 3 | 4 | // accept `key`, if it's a property inside `obj` 5 | const getValue = function( obj: V, key: K ): any { 6 | return obj[ key ]; 7 | }; 8 | 9 | // keyof (typeof car) => 'name' | 'model' 10 | getValue( car, 'name' ); 11 | getValue( car, 'model' ); 12 | 13 | // keyof (typeof fruit) => 'type' | 'color' | 'weight' 14 | getValue( fruit, 'color' ); 15 | getValue( fruit, 'weight' ); 16 | 17 | // Error: Argument of type 'string' is not assignable to parameter of type '"color" | "type" | "weight"'. 18 | getValue( fruit, 'color' as string ); 19 | 20 | // Error: Argument of type '"name"' is not assignable to parameter of type '"color" | "type" | "weight"'. 21 | getValue( fruit, 'name' ); -------------------------------------------------------------------------------- /generics/generic-function-multiple-placeholders.ts: -------------------------------------------------------------------------------- 1 | // declare `getTuple` of the type of a generic function 2 | var getTuple: ( a: T, b: U ) => [ T, U ] = ( a, b ) => { 3 | return [ a, b ]; 4 | } 5 | 6 | // var stringArray: [string, string] 7 | var stringArray = getTuple( 'hello', 'world' ); 8 | 9 | // var numberArray: [number, number] 10 | var numberArray = getTuple( 1.25, 2.56 ); 11 | 12 | // var mixedArray: [number, string] 13 | var mixedArray = getTuple( 1.25, 'world' ); -------------------------------------------------------------------------------- /generics/generic-interface-extended.ts: -------------------------------------------------------------------------------- 1 | // declare a generic interface with a genetic method 2 | interface TupleObject { 3 | a: T; 4 | b: U; 5 | getTuple( c: V ): [ T, U, V ]; 6 | } 7 | 8 | // var tupleObj: TupleObject 9 | var tupleObj: TupleObject = { 10 | a: '1', 11 | b: 2, 12 | getTuple( c ) { 13 | return [ this.a, this.b, c ]; 14 | } 15 | }; 16 | 17 | // var tuple: [string, number, boolean] 18 | var tuple = tupleObj.getTuple( true ); 19 | console.log( 'tuple =>', tuple ); -------------------------------------------------------------------------------- /generics/generic-interface-for-class-instance-side.ts: -------------------------------------------------------------------------------- 1 | // declare a generic interface 2 | interface Secret { 3 | secret: T; 4 | } 5 | 6 | // implement a generic interfacd 7 | class Student implements Secret { 8 | 9 | // Error: Type 'string' is not assignable to type 'number'. 10 | public secret: string; 11 | 12 | constructor( value: string ){ 13 | this.secret = value; 14 | } 15 | } -------------------------------------------------------------------------------- /generics/generic-interface-function-type.ts: -------------------------------------------------------------------------------- 1 | // declare a generic function using interface 2 | interface TupleFunction { 3 | ( a: T, b: U ): [ T, U ]; 4 | } 5 | 6 | // declare a function of type `TupleFunction` 7 | var getTuple: TupleFunction = ( a, b ) => { 8 | return [ a, b ]; 9 | } 10 | 11 | // var stringArray: [string, string] 12 | var stringArray = getTuple( 'hello', 'world' ); 13 | 14 | // var numberArray: [number, number] 15 | var numberArray = getTuple( 1.25, 2.56 ); 16 | 17 | // var mixedArray: [number, string] 18 | var mixedArray = getTuple( 1.25, 'world' ); -------------------------------------------------------------------------------- /generics/generic-interface.ts: -------------------------------------------------------------------------------- 1 | // define a generic interface 2 | interface TupleObject { 3 | a: T; 4 | b: U; 5 | getTuple(): [ T, U ]; 6 | } 7 | 8 | // var tupleObj1: TupleObject 9 | var tupleObj1: TupleObject = { 10 | a: 1, 11 | b: 2, 12 | getTuple: function() { 13 | return [ this.a, this.b ]; 14 | } 15 | }; 16 | 17 | // var tuple1: [string, number] 18 | var tuple1 = tupleObj1.getTuple(); 19 | console.log( 'tuple1 =>', tuple1 ); 20 | 21 | // var tupleObj2: TupleObject 22 | var tupleObj2: TupleObject = { 23 | a: '1', 24 | b: 2, 25 | getTuple: function() { 26 | return [ this.a, this.b ]; 27 | } 28 | }; 29 | 30 | // var tuple2: [number, number] 31 | var tuple2 = tupleObj1.getTuple(); 32 | console.log( 'tuple2 =>', tuple2 ); -------------------------------------------------------------------------------- /generics/simple-function.ts: -------------------------------------------------------------------------------- 1 | // union of `string` and `number` 2 | type NS = string | number; 3 | 4 | // function that returns a tuple 5 | function getTuple( a: NS, b: NS ): [ NS, NS ] { 6 | return [ a, b ]; 7 | } 8 | 9 | // let stringArray: [NS, NS] 10 | var stringArray = getTuple( 'hello', 'world' ); 11 | 12 | // let numberArray: [NS, NS] 13 | var numberArray = getTuple( 1.25, 2.56 ); 14 | 15 | // let mixedArray: [NS, NS] 16 | var mixedArray = getTuple( 1.25, 'world' ); 17 | 18 | // Property 'toUpperCase' does not exist on type 'NS'. 19 | console.log( stringArray.map( s => s.toUpperCase() ) ); 20 | 21 | // Error: Property 'toFixed' does not exist on type 'NS'. 22 | console.log( numberArray.map( n => n.toFixed() ) ); -------------------------------------------------------------------------------- /generics/simple-generic-function.ts: -------------------------------------------------------------------------------- 1 | // function that returns a tuple 2 | function getTuple( a: T, b: T ): [ T, T ] { 3 | return [ a, b ]; 4 | } 5 | 6 | // var stringArray: [string, string] 7 | var stringArray = getTuple( 'hello', 'world' ); 8 | 9 | // var numberArray: [number, number] 10 | var numberArray = getTuple( 1.25, 2.56 ); 11 | 12 | // var ucStrings: string[] 13 | var ucStrings = stringArray.map( s => s.toUpperCase() ); 14 | 15 | // var numInts: string[] 16 | var numInts = numberArray.map( n => n.toFixed() ); 17 | 18 | // var mixedArray: [number, number] 19 | // Error: Argument of type '"world"' is not assignable to parameter of type 'number'. 20 | var mixedArray = getTuple( 1.25, 'world' ); -------------------------------------------------------------------------------- /hello-world/hello-world-with-tsconfig/build/lib/utils.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.__esModule = true; 3 | exports.sayHello = void 0; 4 | function sayHello(user) { 5 | return "Hello, " + user; 6 | } 7 | exports.sayHello = sayHello; 8 | -------------------------------------------------------------------------------- /hello-world/hello-world-with-tsconfig/build/program.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.__esModule = true; 3 | var utils_1 = require("./lib/utils"); 4 | // declare `result` of type `string` 5 | var result; 6 | // save return value of `sayHello()` in `result` 7 | result = utils_1.sayHello('Ross'); 8 | // print result 9 | console.log(result); 10 | -------------------------------------------------------------------------------- /hello-world/hello-world-with-tsconfig/dist/lib/utils.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.__esModule = true; 3 | exports.sayHello = void 0; 4 | function sayHello(user) { 5 | return "Hello, " + user; 6 | } 7 | exports.sayHello = sayHello; 8 | -------------------------------------------------------------------------------- /hello-world/hello-world-with-tsconfig/dist/program.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.__esModule = true; 3 | var utils_1 = require("./lib/utils"); 4 | // declare `result` of type `string` 5 | var result; 6 | // save return value of `sayHello()` in `result` 7 | result = utils_1.sayHello('Ross'); 8 | // print result 9 | console.log(result); 10 | -------------------------------------------------------------------------------- /hello-world/hello-world-with-tsconfig/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | export function sayHello( user: string ): string { 2 | return `Hello, ${ user }`; 3 | } -------------------------------------------------------------------------------- /hello-world/hello-world-with-tsconfig/src/program.ts: -------------------------------------------------------------------------------- 1 | import { sayHello } from './lib/utils'; 2 | 3 | // declare `result` of type `string` 4 | var result: string; 5 | 6 | // save return value of `sayHello()` in `result` 7 | result = sayHello( 'Ross' ); 8 | 9 | // print result 10 | console.log( result ); -------------------------------------------------------------------------------- /hello-world/hello-world-with-tsconfig/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "./src/program.ts", 4 | "./src/lib/utils.ts" 5 | ], 6 | "compilerOptions": { 7 | "outDir": "./dist" 8 | } 9 | } -------------------------------------------------------------------------------- /hello-world/hello-world-with-types/dist/lib/utils.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.__esModule = true; 3 | exports.sayHello = void 0; 4 | function sayHello(user) { 5 | return "Hello, " + user; 6 | } 7 | exports.sayHello = sayHello; -------------------------------------------------------------------------------- /hello-world/hello-world-with-types/dist/program.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.__esModule = true; 3 | var utils_1 = require("./lib/utils"); 4 | // declare `result` of type `string` 5 | var result; 6 | // save return value of `sayHello()` in `result` 7 | result = utils_1.sayHello('Ross'); 8 | // print result 9 | console.log(result); -------------------------------------------------------------------------------- /hello-world/hello-world-with-types/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | export function sayHello( user: string ): string { 2 | return `Hello, ${ user }`; 3 | } -------------------------------------------------------------------------------- /hello-world/hello-world-with-types/src/program.ts: -------------------------------------------------------------------------------- 1 | import { sayHello } from './lib/utils'; 2 | 3 | // declare `result` of type `string` 4 | var result: string; 5 | 6 | // save return value of `sayHello()` in `result` 7 | result = sayHello( 'Ross' ); 8 | 9 | // print result 10 | console.log( result ); -------------------------------------------------------------------------------- /hello-world/hello-world/hello.js: -------------------------------------------------------------------------------- 1 | console.log('Hello World!'); -------------------------------------------------------------------------------- /hello-world/hello-world/hello.ts: -------------------------------------------------------------------------------- 1 | console.log( 'Hello World!' ); -------------------------------------------------------------------------------- /interfaces/.gitignore: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /interfaces/argument-with-interface.ts: -------------------------------------------------------------------------------- 1 | // define `Person` interface 2 | interface Person { 3 | firstName: string; 4 | lastName: string; 5 | age: number; 6 | getSalary: (base: number) => number; 7 | }; 8 | 9 | // define an object of type `Person` 10 | let ross: Person = { 11 | firstName: 'Ross', 12 | lastName: 'Geller', 13 | age: 32, 14 | getSalary: ( base: number ) => base * 12 15 | }; 16 | 17 | // function that returns info of a `Person` object 18 | let getPersonInfo = ( person: Person ): string => { 19 | return `Hello, ${ person.firstName } ${ person.lastName }.`; 20 | }; 21 | 22 | // get person information 23 | console.log( getPersonInfo( ross ) ); -------------------------------------------------------------------------------- /interfaces/argument-with-shape.ts: -------------------------------------------------------------------------------- 1 | // define a plain object 2 | let ross = { 3 | firstName: 'Ross', 4 | lastName: 'Geller', 5 | age: 32, 6 | getSalary: ( base: number ) => base * 12 7 | }; 8 | 9 | // function that accepts object as an argument 10 | let getPersonInfo = ( arg: { 11 | firstName: string; 12 | lastName: string; 13 | age: number; 14 | getSalary: (base: number) => number; 15 | } ): string => { 16 | return `Hello, ${ arg.firstName } ${ arg.lastName }.`; 17 | }; 18 | 19 | // get person information 20 | console.log( getPersonInfo( ross ) ); -------------------------------------------------------------------------------- /interfaces/extend-interface.ts: -------------------------------------------------------------------------------- 1 | // define `Person` interface 2 | interface Person { 3 | firstName: string; 4 | lastName: string; 5 | } 6 | 7 | // `Student` interface inherits `Person` 8 | interface Student extends Person { 9 | rollNo: number; 10 | } 11 | 12 | // define `monica` of type `Person` 13 | let monica: Person = { 14 | firstName: 'Monica', 15 | lastName: 'Geller' 16 | }; 17 | 18 | // define `ross` object of type `Student` 19 | let ross: Student = { 20 | firstName: 'Ross', 21 | lastName: 'Geller', 22 | rollNo: 100 23 | }; 24 | 25 | // log values 26 | console.log( 'monica =>', monica ); 27 | console.log( 'Ross =>', ross ); -------------------------------------------------------------------------------- /interfaces/extend-multiple-interfaces.ts: -------------------------------------------------------------------------------- 1 | // define `Person` interface 2 | interface Person { 3 | firstName: string; 4 | lastName: string; 5 | } 6 | 7 | // define `Player` interface 8 | interface Player { 9 | score: number; 10 | } 11 | 12 | // `Student` interface inherits `Person` and `Player` 13 | interface Student extends Person, Player { 14 | rollNo: number; 15 | } 16 | 17 | // create `ross` object of type `Student` 18 | let ross: Student = { 19 | firstName: 'Ross', 20 | lastName: 'Geller', 21 | score: 85, 22 | rollNo: 100, 23 | }; 24 | 25 | // log values 26 | console.log( 'ross =>', ross ); -------------------------------------------------------------------------------- /interfaces/function-signature-with-methods.ts: -------------------------------------------------------------------------------- 1 | // declare a function type with properties 2 | interface IsSumOdd { 3 | ( a: number, b: number ): boolean; 4 | type: string; 5 | calculate( a: number, b: number): number; 6 | } 7 | 8 | // create a function of type `IsSumOdd` 9 | let isSumOdd: IsSumOdd = Object.assign( 10 | function( x: number, y: number ): boolean { 11 | return (x + y) % 2 !== 0; 12 | }, 13 | 14 | // assign properties 15 | { 16 | type: 'oddChecker', 17 | calculate: function( x: number, y: number ): number { 18 | return x + y; 19 | } 20 | } 21 | ); 22 | 23 | // log some values 24 | console.log( 'isSumOdd(1, 2) =>', isSumOdd(1, 2) ); 25 | console.log( 'isSumOdd.type =>', isSumOdd.type ); 26 | console.log( 'isSumOdd.calculate(1, 2) =>', isSumOdd.calculate(1, 2) ); -------------------------------------------------------------------------------- /interfaces/function-signature-with-new.ts: -------------------------------------------------------------------------------- 1 | // define a class 2 | class Animal { 3 | sound: string 4 | 5 | constructor( sound: string ) { 6 | this.sound = sound; 7 | } 8 | 9 | getSound(): string { 10 | return `${ this.sound }! ${ this.sound }!`; 11 | } 12 | } 13 | 14 | // define an interface to represent a constructor function 15 | interface AnimalInterface { 16 | new ( sound: string ): Animal; 17 | } 18 | 19 | // create `Animal` factory function 20 | let createAnimal = ( ctor: AnimalInterface, type: string ): Animal => { 21 | return type === 'dog' ? new ctor( 'Woof' ) : new ctor( 'Meow' ); 22 | } 23 | 24 | // create `Animal` instance 25 | let dog: Animal = createAnimal( Animal, 'dog' ); 26 | console.log( 'dog.getSound() =>', dog.getSound() ); -------------------------------------------------------------------------------- /interfaces/function-signature.ts: -------------------------------------------------------------------------------- 1 | // declare a function type 2 | interface IsSumOdd { 3 | ( a: number, b: number ): boolean; 4 | } 5 | 6 | // create a function of type `IsSumOdd` 7 | let isSumOdd: IsSumOdd = ( x: number, y: number ): boolean => { 8 | if( (x + y) % 2 === 0 ) { 9 | return false; 10 | } 11 | 12 | return true; 13 | }; 14 | 15 | // make some `isSumOdd()` calls 16 | console.log( 'isSumOdd(1, 2) =>', isSumOdd(1, 2) ); 17 | console.log( 'isSumOdd(2, 2) =>', isSumOdd(2, 2) ); 18 | -------------------------------------------------------------------------------- /interfaces/indexable-type-number.ts: -------------------------------------------------------------------------------- 1 | // declare indexable interface type 2 | interface LapTimes { 3 | [key: number]: number; 4 | } 5 | 6 | // declare some valuesof type `LapTimes` 7 | let ross: LapTimes = [ 10.5, 11.6, 10.9 ]; 8 | let monica: LapTimes = { 0: 10.5, 1: 11.6, 2: 10.9 }; 9 | let joey: LapTimes = { '0': 10.5, '1': 11.6, '2': 10.9 }; 10 | let rachel: LapTimes = { 'one': 10.5, 'two': 11.6, 'three': 10.9 }; -------------------------------------------------------------------------------- /interfaces/indexable-type-object.ts: -------------------------------------------------------------------------------- 1 | // declare indexable interface type 2 | interface SimpleObject { 3 | [key: string]: any; 4 | } 5 | 6 | // declare few objects of type `SimpleObject` 7 | let ross: SimpleObject = { name: 'Ross Geller', age: 32 }; 8 | let monica: SimpleObject = { name: 'Monica Geller', 1: 28 }; 9 | 10 | // print values 11 | console.log( 'ross =>', ross ); 12 | console.log( 'monica =>', monica ); -------------------------------------------------------------------------------- /interfaces/indexable-type-required-properties.ts: -------------------------------------------------------------------------------- 1 | // declare indexable interface type 2 | interface LapTimes { 3 | name: string; 4 | age?: number; 5 | [key: number]: number; 6 | } 7 | 8 | // valid 9 | let ross: LapTimes = { 10 | name: 'Ross Geller', 11 | 0: 10.3, 12 | 1: 11.2 13 | }; 14 | 15 | // Error: Type 'string' is not assignable to type 'number | undefined'. 16 | let monica: LapTimes = { 17 | name: 'Monica Geller', 18 | age: '28', 19 | 0: 10.3, 1: 11.2 20 | }; 21 | 22 | // Error: Object literal may only specify known properties, and 'gender' does not exist in type 'LapTimes'. 23 | let joey: LapTimes = { 24 | name: 'Monica Geller', 25 | gender: 'Male', 26 | 0: 10.3, 27 | 1: 11.2 28 | }; 29 | 30 | // Error: Property 'name' is missing in type '{ 0: number; 1: number; }' but required in type 'LapTimes'. 31 | let rachel: LapTimes = { 32 | 0: 10.3, 33 | 1: 11.2 34 | }; -------------------------------------------------------------------------------- /interfaces/interface-safety.ts: -------------------------------------------------------------------------------- 1 | // define `Student` interface 2 | interface Student { 3 | firstName: string; 4 | lastName: string; 5 | age: number; 6 | getSalary: (base: number) => number; 7 | }; 8 | 9 | // define an object of type `Student` 10 | let student: Student = { 11 | firstName: 'Ross', 12 | lastName: 'Geller', 13 | age: 32, 14 | getSalary: ( base: number ) => base * 12 15 | }; 16 | 17 | // function that prints student info 18 | let printStudent = ( _student: Student ): void => { 19 | // property doesn't exist 20 | console.log( _student.name ); 21 | 22 | // arithmetic operation with `string` value 23 | console.log( 100 - _student.firstName ); 24 | }; 25 | 26 | // print student info 27 | printStudent( student ); -------------------------------------------------------------------------------- /interfaces/merged-interface.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | firstName: string; 3 | } 4 | 5 | interface Person { 6 | lastName: string; 7 | } 8 | 9 | interface Person { 10 | firstName: string; 11 | rollNo: number; 12 | } 13 | 14 | // create an object of type `Person` 15 | const ross: Person = { 16 | firstName: 'Ross', 17 | lastName: 'Geller', 18 | rollNo: 100 19 | }; 20 | 21 | // log values 22 | console.log( 'ross =>', ross ); -------------------------------------------------------------------------------- /interfaces/nested-interface.ts: -------------------------------------------------------------------------------- 1 | // define `Person` interface 2 | interface Person { 3 | firstName: string; 4 | lastName: string; 5 | } 6 | 7 | // define `Student` interface 8 | interface Student { 9 | info: Person; 10 | rollNo: number; 11 | } 12 | 13 | // define `ross` object of type `Student` 14 | let ross: Student = { 15 | info: { 16 | firstName: 'Ross', 17 | lastName: 'Geller', 18 | }, 19 | rollNo: 100 20 | }; 21 | 22 | // log values 23 | console.log( 'ross =>', ross ); -------------------------------------------------------------------------------- /interfaces/nested-shape.ts: -------------------------------------------------------------------------------- 1 | // define `Student` interface 2 | interface Student { 3 | info: { 4 | firstName: string; 5 | lastName: string; 6 | }; 7 | rollNo: number; 8 | } 9 | 10 | // define `ross` object of type `Student` 11 | let ross: Student = { 12 | info: { 13 | firstName: 'Ross', 14 | lastName: 'Geller', 15 | }, 16 | rollNo: 100 17 | }; 18 | 19 | // log values 20 | console.log( 'ross =>', ross ); -------------------------------------------------------------------------------- /interfaces/object-shape.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | // define a plain object 7 | let student = { 8 | firstName: 'Ross', 9 | lastName: 'Geller', 10 | age: 32, 11 | getSalary: ( base: number ) => base * 12 12 | }; -------------------------------------------------------------------------------- /interfaces/optional-properties-safety-override.ts: -------------------------------------------------------------------------------- 1 | // define `Student` interface 2 | interface Student { 3 | firstName: string; 4 | lastName: string; 5 | age?: number; 6 | }; 7 | 8 | // define `ross` object 9 | let ross: Student = { 10 | firstName: 'Ross', 11 | lastName: 'Geller', 12 | age: 32 13 | }; 14 | 15 | // get age of a student after 10 years 16 | let getAge = ( _student: Student ): number => { 17 | return ( _student.age as number ) + 10; 18 | }; 19 | 20 | console.log( getAge( ross ) ); -------------------------------------------------------------------------------- /interfaces/optional-properties-safety.ts: -------------------------------------------------------------------------------- 1 | // define `Student` interface 2 | interface Student { 3 | firstName: string; 4 | lastName: string; 5 | age?: number; 6 | }; 7 | 8 | // define `ross` object 9 | let ross: Student = { 10 | firstName: 'Ross', 11 | lastName: 'Geller', 12 | age: 32 13 | }; 14 | 15 | // get age of a student after 10 years 16 | let getAge = ( _student: Student ): number => { 17 | return _student.age + 10; 18 | }; 19 | 20 | console.log( getAge( ross ) ); -------------------------------------------------------------------------------- /interfaces/optional-properties.ts: -------------------------------------------------------------------------------- 1 | // define `Student` interface 2 | interface Student { 3 | firstName: string; 4 | lastName: string; 5 | age?: number; 6 | getSalary: (base: number) => number; 7 | }; 8 | 9 | // create `ross` object of type `Student` 10 | let ross: Student = { 11 | firstName: 'Ross', 12 | lastName: 'Geller', 13 | getSalary: ( base: number ) => base * 12 14 | }; 15 | 16 | // define `monica` object 17 | let monica: Student = { 18 | firstName: 'Monica', 19 | lastName: 'Geller', 20 | age: '21', // Error 21 | getSalary: ( base: number ) => base * 12 22 | }; -------------------------------------------------------------------------------- /interfaces/readonly-properties.ts: -------------------------------------------------------------------------------- 1 | // define `Student` interface 2 | interface Student { 3 | firstName: string; 4 | lastName: string; 5 | age?: number; 6 | readonly getSalary: (base: number) => number; 7 | }; 8 | 9 | // define `ross` object 10 | let ross: Student = { 11 | firstName: 'Ross', 12 | lastName: 'Geller', 13 | getSalary: ( base: number ) => base * 12 14 | }; 15 | 16 | -------------------------------------------------------------------------------- /interfaces/shape-override-any.ts: -------------------------------------------------------------------------------- 1 | // define ross object 2 | let ross: any = { 3 | firstName: 'Ross', 4 | lastName: 'Geller', 5 | age: 32, 6 | getSalary: ( base: number ) => base * 12 7 | }; 8 | 9 | // override `getSalary` property value 10 | ross.getSalary = 1200; 11 | 12 | /// add `email` property with a default value 13 | ross.email = 'ross@geller.com'; 14 | 15 | // log `ross` object 16 | console.log( ross ); -------------------------------------------------------------------------------- /interfaces/shape-override.ts: -------------------------------------------------------------------------------- 1 | // define ross object 2 | let ross = { 3 | firstName: 'Ross', 4 | lastName: 'Geller', 5 | age: 32, 6 | getSalary: ( base: number ) => base * 12 7 | }; 8 | 9 | // override `getSalary` property value 10 | ross.getSalary = 1200; 11 | 12 | /// add `email` property with a default value 13 | ross.email = 'ross@geller.com'; -------------------------------------------------------------------------------- /introduction/fixed/program-fixed.js: -------------------------------------------------------------------------------- 1 | var x = '1'; 2 | var y; 3 | console.log(typeof x, typeof y); 4 | 5 | x = 'hello'; 6 | y = 2; 7 | console.log(typeof x, typeof y); 8 | 9 | x = 'true'; 10 | y = 3; 11 | console.log(typeof x, typeof y); -------------------------------------------------------------------------------- /introduction/fixed/program-fixed.ts: -------------------------------------------------------------------------------- 1 | var x: string = '1'; 2 | var y: number; 3 | console.log( typeof x, typeof y ); 4 | 5 | x = 'hello'; 6 | y = 2; 7 | console.log( typeof x, typeof y ); 8 | 9 | x = 'true'; 10 | y = 3; 11 | console.log( typeof x, typeof y ); -------------------------------------------------------------------------------- /introduction/initial/program.js: -------------------------------------------------------------------------------- 1 | var x = 1; 2 | var y; 3 | console.log(typeof x, typeof y); 4 | x = 'hello'; 5 | y = 'world'; 6 | console.log(typeof x, typeof y); 7 | x = true; 8 | y = x; 9 | console.log(typeof x, typeof y); 10 | -------------------------------------------------------------------------------- /introduction/initial/program.ts: -------------------------------------------------------------------------------- 1 | var x: string = 1; 2 | var y: number; 3 | console.log( typeof x, typeof y ); 4 | 5 | x = 'hello'; 6 | y = 'world'; 7 | console.log( typeof x, typeof y ); 8 | 9 | x = true; 10 | y = x; 11 | console.log( typeof x, typeof y ); -------------------------------------------------------------------------------- /introduction/raw/program.js: -------------------------------------------------------------------------------- 1 | var x = 1; 2 | var y; 3 | console.log( typeof x, typeof y ); // number undefined 4 | 5 | x = 'hello'; 6 | y = 'world'; 7 | console.log( typeof x, typeof y ); // string string 8 | 9 | x = true; 10 | y = x; 11 | console.log( typeof x, typeof y ); // boolean boolean -------------------------------------------------------------------------------- /introduction/target-tsconfig/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "./program.ts" 4 | ], 5 | "compilerOptions": { 6 | "outDir": "./dist", 7 | "target": "ES5", 8 | "module": "CommonJS" 9 | } 10 | } -------------------------------------------------------------------------------- /module-system/.gitignore: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /module-system/dist/api.d.ts: -------------------------------------------------------------------------------- 1 | export { Institution as School } from './models/Institution'; 2 | export { default, Teacher, Student } from './models/Role'; 3 | import { Institution as School } from './models/Institution'; 4 | export declare const getSchool: () => School; 5 | -------------------------------------------------------------------------------- /module-system/dist/models/Institution.d.ts: -------------------------------------------------------------------------------- 1 | import Roles, { Role as Person, Student, Teacher } from './Role'; 2 | export declare class Institution { 3 | private students; 4 | private teachers; 5 | constructor(students?: Student[], teachers?: Teacher[]); 6 | addPerson(person: Person): Institution; 7 | findPerson(id: number, kind?: Roles): Person; 8 | } 9 | -------------------------------------------------------------------------------- /module-system/dist/models/Role.d.ts: -------------------------------------------------------------------------------- 1 | import { RoleInterface } from './types'; 2 | declare enum Roles { 3 | Student = 0, 4 | Teacher = 1 5 | } 6 | declare class Role implements RoleInterface { 7 | id: number; 8 | firstName: string; 9 | lastName: string; 10 | constructor(id: number, firstName: string, lastName: string); 11 | getFullName(): string; 12 | } 13 | declare class Student extends Role { 14 | private dob; 15 | constructor(id: number, firstName: string, lastName: string, _dob: string); 16 | getAge(): number; 17 | } 18 | declare class Teacher extends Role { 19 | private subjects; 20 | constructor(id: number, firstName: string, lastName: string, subjects: string); 21 | canTeach(subject: string): boolean; 22 | } 23 | export { Roles as default, Role, Student, Teacher }; 24 | -------------------------------------------------------------------------------- /module-system/dist/models/types.d.ts: -------------------------------------------------------------------------------- 1 | export interface RoleInterface { 2 | id: number; 3 | firstName: string; 4 | lastName: string; 5 | } 6 | -------------------------------------------------------------------------------- /module-system/dist/utils/getAge.d.ts: -------------------------------------------------------------------------------- 1 | declare const _default: (date: Date) => number; 2 | /** 3 | * @example 4 | * import getAge from 'path/to/getAge'; 5 | */ 6 | export default _default; 7 | -------------------------------------------------------------------------------- /module-system/lib/api.ts: -------------------------------------------------------------------------------- 1 | // re-export classes 2 | export { Institution as School } from './models/Institution'; 3 | export { default, Teacher, Student } from './models/Role'; 4 | 5 | // imports 6 | import { Institution as School } from './models/Institution'; 7 | 8 | // single instance of `School` class 9 | let school: School = undefined; 10 | 11 | // get singleton instance 12 | export const getSchool = (): School => { 13 | if( school === undefined ) { 14 | school = new School(); 15 | } 16 | 17 | return school; 18 | }; -------------------------------------------------------------------------------- /module-system/lib/models/Institution.ts: -------------------------------------------------------------------------------- 1 | // imports 2 | import Roles, { 3 | Role as Person, Student, Teacher 4 | } from './Role'; 5 | 6 | export class Institution { 7 | constructor( 8 | private students: Student[] = [], 9 | private teachers: Teacher[] = [] 10 | ) {} 11 | 12 | addPerson( person: Person ): Institution { 13 | if( person instanceof Student ) { 14 | this.students.push( person ); 15 | } else if( person instanceof Teacher ) { 16 | this.teachers.push( person ); 17 | } 18 | 19 | return this; // to make this method chainable 20 | } 21 | 22 | findPerson( id: number, kind = Roles.Student ): Person { 23 | if( kind === Roles.Student ) { 24 | return this.students.find( ( student ) => { 25 | return student.id === id; 26 | } ); 27 | } else { 28 | return this.teachers.find( ( teacher ) => { 29 | return teacher.id === id; 30 | } ); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /module-system/lib/models/Role.ts: -------------------------------------------------------------------------------- 1 | // imports 2 | import getAge from '../utils/getAge'; 3 | import { RoleInterface } from './types'; 4 | 5 | enum Roles { 6 | Student, 7 | Teacher, 8 | } 9 | 10 | class Role implements RoleInterface{ 11 | constructor( 12 | public id: number, 13 | public firstName: string, 14 | public lastName: string 15 | ){} 16 | 17 | getFullName(): string { 18 | return `${ this.firstName } ${ this.lastName }`; 19 | } 20 | } 21 | 22 | class Student extends Role { 23 | private dob: Date; 24 | 25 | constructor( id: number, firstName: string, lastName: string, _dob: string ){ 26 | super( id, firstName, lastName ); 27 | this.dob = new Date( _dob ); 28 | } 29 | 30 | getAge(): number { 31 | return getAge( this.dob ); 32 | } 33 | } 34 | 35 | class Teacher extends Role { 36 | private subjects: string[]; 37 | 38 | constructor( id: number, firstName: string, lastName: string, subjects: string ){ 39 | super( id, firstName, lastName ); 40 | this.subjects = subjects.split( ',' ); 41 | } 42 | 43 | canTeach( subject: string ): boolean { 44 | return this.subjects.includes( subject ); 45 | } 46 | } 47 | 48 | export { Roles as default, Role, Student, Teacher }; -------------------------------------------------------------------------------- /module-system/lib/models/types.ts: -------------------------------------------------------------------------------- 1 | export interface RoleInterface { 2 | id: number; 3 | firstName: string; 4 | lastName: string; 5 | } -------------------------------------------------------------------------------- /module-system/lib/utils/getAge.ts: -------------------------------------------------------------------------------- 1 | import * as moment from 'moment'; 2 | 3 | /** 4 | * @example 5 | * import getAge from 'path/to/getAge'; 6 | */ 7 | export default ( date: Date ): number => { 8 | // (method) moment.Moment.diff(b: moment.MomentInput, unitOfTime?: moment.unitOfTime.Diff, precise?: boolean): number 9 | 10 | return moment().diff( date, 'years' ); 11 | }; -------------------------------------------------------------------------------- /module-system/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "module-system", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@types/moment": { 8 | "version": "2.13.0", 9 | "resolved": "https://registry.npmjs.org/@types/moment/-/moment-2.13.0.tgz", 10 | "integrity": "sha1-YE69GJvDvDShVIaJQE5hoqSqyJY=", 11 | "requires": { 12 | "moment": "*" 13 | } 14 | }, 15 | "moment": { 16 | "version": "2.26.0", 17 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.26.0.tgz", 18 | "integrity": "sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw==" 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /module-system/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "school", 3 | "version": "1.0.0", 4 | "main": "./dist/api.js", 5 | "typings": "./dist/api.d.ts", 6 | "dependencies": { 7 | "@types/moment": "^2.13.0", 8 | "moment": "^2.26.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /module-system/src/program.ts: -------------------------------------------------------------------------------- 1 | // imports 2 | import Types, { 3 | getSchool, School, Teacher, Student 4 | } from '../lib/api'; 5 | 6 | // get default `School` instance 7 | const school: School = getSchool(); 8 | 9 | // create people for the school 10 | const monica = new Student( 1, 'Monica', 'Geller', '04-22-1969' ); 11 | const rachel = new Student( 2, 'Rachel', 'Green', '05-05-1969' ); 12 | const phoebe = new Student( 3, 'Phoebe', 'Buffay', '02-16-1970' ); 13 | const ross = new Teacher( 1, 'Ross', 'Geller', 'Paleontology,Music' ); 14 | const joey = new Teacher( 2, 'Joey', 'Tribbiani', 'Dance,Acting' ); 15 | 16 | // add students to school 17 | school.addPerson( ross ); 18 | school.addPerson( joey ); 19 | school.addPerson( monica ); 20 | school.addPerson( rachel ); 21 | school.addPerson( phoebe ); 22 | 23 | // find people in the school 24 | const s = school.findPerson( 1, Types.Student ); 25 | const t = school.findPerson( 2, Types.Teacher ); 26 | 27 | console.log( 28 | 'Student %s is %d years old.', 29 | s.getFullName(), (s as Student).getAge() 30 | ); 31 | 32 | console.log( 33 | 'Can teacher %s teach dance? %s.', 34 | t.getFullName(), (t as Teacher).canTeach( 'Dance' ) 35 | ); -------------------------------------------------------------------------------- /module-system/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "Node", 4 | "module": "CommonJS", 5 | "target": "ES2017" 6 | } 7 | } -------------------------------------------------------------------------------- /module-system/tsconfig.publish.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "./lib/api.ts" 4 | ], 5 | "compilerOptions": { 6 | "target": "ES2018", 7 | "module": "CommonJS", 8 | "outDir": "./dist", 9 | "declaration": true 10 | } 11 | } -------------------------------------------------------------------------------- /polymorphism/class-polymorphism.ts: -------------------------------------------------------------------------------- 1 | class Person { 2 | constructor( 3 | public firstName: string, 4 | public lastName: string 5 | ){} 6 | 7 | getFullName(): string { 8 | return `${ this.firstName } ${ this.lastName }`; 9 | } 10 | } 11 | 12 | class Student extends Person { 13 | constructor( 14 | firstName: string, 15 | lastName: string, 16 | public marks: number 17 | ){ super( firstName, lastName ); } 18 | } 19 | 20 | // print name of a `Person` object 21 | const printName = ( person: Person ) => { 22 | return person.getFullName(); 23 | }; 24 | 25 | // objects of the shape of `Person` 26 | let ross = new Person( 'Ross', 'Geller' ); 27 | let monica = new Student( 'Monica', 'Geller', 86 ); 28 | let judy = { firstName: 'Judy', lastName: 'Geller' }; 29 | let jack = { 30 | firstName: 'Jack', 31 | lastName: 'Geller', 32 | getFullName(): string { 33 | return `${ this.firstName } ${ this.lastName }`; 34 | } 35 | }; 36 | 37 | // print full-names of the objects 38 | console.log( printName( ross ) ); 39 | console.log( printName( monica ) ); 40 | console.log( printName( jack ) ); // legal 41 | 42 | // Error: Argument of type '{ firstName: string; lastName: string; }' is not assignable to parameter of type 'Person'. 43 | console.log( printName( judy ) ); -------------------------------------------------------------------------------- /polymorphism/instanceof-operator.js: -------------------------------------------------------------------------------- 1 | class Person { 2 | constructor( firstName, lastName ){ 3 | this.firstName = firstName; 4 | this.lastName = lastName; 5 | } 6 | 7 | getFullName() { 8 | return `${ this.firstName } ${ this.lastName }`; 9 | } 10 | } 11 | 12 | // class `Student` inherits `Person` 13 | class Student extends Person { 14 | constructor( firstName, lastName, marks ){ 15 | super( firstName, lastName ); 16 | this.marks = marks; 17 | } 18 | } 19 | 20 | // get full-name of a `Person` object 21 | const printName = ( person ) => { 22 | return person instanceof Person ? 23 | person.getFullName(): 'Oops! Not a Person!'; 24 | }; 25 | 26 | // objects of the shape of `Person` 27 | let ross = new Person( 'Ross', 'Geller' ); 28 | let monica = new Student( 'Monica', 'Geller', 86 ); 29 | let jack = { 30 | firstName: 'Jack', 31 | lastName: 'Geller', 32 | getFullName: () => null, 33 | }; 34 | 35 | // get full-names of the objects 36 | console.log( printName( ross ) ); 37 | console.log( printName( monica ) ); 38 | console.log( printName( jack ) ); -------------------------------------------------------------------------------- /polymorphism/interface-polymorphism.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | name: string; 3 | getName(): string; 4 | } 5 | 6 | interface Student extends Person { 7 | marks: number; 8 | } 9 | 10 | // print name of a `Person` object 11 | const printName = ( person: Person ) => person.getName(); 12 | 13 | // instance of `Person` 14 | let ross: Person = { 15 | name: 'Ross Geller', 16 | getName() { return this.name; } 17 | }; 18 | 19 | // instance of `Student` 20 | let monica: Student = { 21 | name: 'Monica Geller', 22 | marks: 84, 23 | getName() { return this.name; } 24 | }; 25 | 26 | // plain JavaScript object 27 | let jack = { 28 | name: 'Jack Geller', 29 | age: 60, 30 | getName() { return this.name; } 31 | }; 32 | 33 | // print full-names of the objects 34 | console.log( printName( ross ) ); 35 | console.log( printName( monica ) ); 36 | console.log( printName( jack ) ); -------------------------------------------------------------------------------- /promises-and-async-await/.gitignore: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /promises-and-async-await/async-await-reject.ts: -------------------------------------------------------------------------------- 1 | // resolve with a random integer between 0 and 9 2 | const getRandomInt: () => Promise = async () => { 3 | return parseInt( (Math.random() * 10).toFixed( 0 ) ); 4 | }; 5 | 6 | // resolve with a boolean value 7 | const isEven = async ( answer: boolean ) => { 8 | // const value: number 9 | const value = await getRandomInt(); 10 | 11 | // reject if the `value` is `0` 12 | if( value === 0 ) { 13 | throw new Error( 'Can\'t work with 0 :/' ); 14 | } 15 | 16 | // returned value is `boolean` 17 | const isEven = value % 2 === 0; 18 | return isEven === answer; 19 | }; 20 | 21 | // listen to promise resolution 22 | isEven( true ).then( ( value ) => { 23 | // (parameter) value: boolean 24 | console.log( 25 | value === true ? 'lucky :)' : 'unlucky :(' 26 | ); 27 | } ).catch( ( error: Error ) => { 28 | console.log( 'Rejected:', error.message ); 29 | } ).finally( () => { 30 | console.log( 'Completed!' ); 31 | } ); -------------------------------------------------------------------------------- /promises-and-async-await/async-await-try-catch.ts: -------------------------------------------------------------------------------- 1 | // resolve with a random integer between 0 and 9 2 | // const getRandomInt: () => Promise 3 | const getRandomInt = async () => { 4 | const value = parseInt((Math.random() * 10).toFixed(0)); 5 | 6 | // reject if the `value` is `0` 7 | if( value === 0 ) { 8 | throw new Error( 'Can\'t work with 0 :/' ); 9 | } 10 | 11 | return value; 12 | }; 13 | 14 | // resolve with a boolean value 15 | // const isEven: (answer: boolean) => Promise 16 | const isEven = async ( answer: boolean ) => { 17 | try { 18 | const value = await getRandomInt(); 19 | const isEven = value % 2 === 0; 20 | return isEven === answer; 21 | } catch( e ) { 22 | console.log( 'getRandomInt rejection:', e.message ); 23 | return false; // return `false` deliberately 24 | } 25 | }; 26 | 27 | // listen to promise resolution 28 | isEven( true ).then( ( value ) => { 29 | // (parameter) value: boolean 30 | console.log( 31 | value === true ? 'lucky :)' : 'unlucky :(' 32 | ); 33 | } ).catch( ( error: Error ) => { 34 | console.log( 'Rejected:', error.message ); 35 | } ).finally( () => { 36 | console.log( 'Completed!' ); 37 | } ); -------------------------------------------------------------------------------- /promises-and-async-await/async-await.ts: -------------------------------------------------------------------------------- 1 | // resolve with a random integer between 0 and 9 2 | const getRandomInt: () => Promise = async () => { 3 | return parseInt( (Math.random() * 10).toFixed( 0 ) ); 4 | }; 5 | 6 | // returns a promise of type `Promise` 7 | // const isEven: (answer: boolean) => Promise 8 | const isEven = async ( answer: boolean ) => { 9 | // const value: number 10 | const value = await getRandomInt(); 11 | 12 | // const isEven: boolean 13 | const isEven = value % 2 === 0; 14 | 15 | // return value is `boolean` 16 | return isEven === answer; 17 | }; 18 | 19 | // listen to promise resolution 20 | isEven( true ).then( ( value ) => { 21 | // (parameter) value: boolean 22 | console.log( 23 | value === true ? 'lucky :)' : 'unlucky :(' 24 | ); 25 | } ).catch( ( error ) => { 26 | // (parameter) error: any 27 | console.log( 'Rejected:', error ); 28 | } ).finally( () => { 29 | console.log( 'Completed!' ); 30 | } ); -------------------------------------------------------------------------------- /promises-and-async-await/promise-all-reject.ts: -------------------------------------------------------------------------------- 1 | // a function that return a delayed promise 2 | const getPromise = ( 3 | value: number, delay: number, fail: boolean 4 | ): Promise => { 5 | return new Promise( ( resolve, reject ) => { 6 | setTimeout( 7 | () => fail ? reject( value ) : resolve( value ), 8 | delay 9 | ); 10 | } ); 11 | }; 12 | 13 | // const allPromise: Promise 14 | const allPromise = Promise.all( [ 15 | getPromise( 0, 0, false ), // 0s 16 | getPromise( 1, 2000, false ), // 2s 17 | getPromise( 2, 1000, true ), // 1s (rejects) 18 | ] ); 19 | 20 | // listen to `allPromise` resolution 21 | console.time( 'settled-in' ); 22 | allPromise.then( ( value ) => { 23 | // (parameter) value: number[] 24 | console.log( 'Resolved:', value ); 25 | } ).catch( ( error ) => { 26 | // (parameter) error: any 27 | console.log( 'Rejected:', error ); 28 | } ).finally( () => { 29 | console.timeEnd( 'settled-in' ); 30 | } ); -------------------------------------------------------------------------------- /promises-and-async-await/promise-all-settled.ts: -------------------------------------------------------------------------------- 1 | // a function that return a delayed promise 2 | const getPromise = ( 3 | value: number, delay: number, fail: boolean 4 | ): Promise => { 5 | return new Promise( ( resolve, reject ) => { 6 | setTimeout( 7 | () => fail ? reject( value ) : resolve( value ), 8 | delay 9 | ); 10 | } ); 11 | }; 12 | 13 | /* const allPromise: Promise[ 14 | PromiseSettledResult, 15 | PromiseSettledResult, 16 | PromiseSettledResult 17 | ]> */ 18 | const allPromise = Promise.allSettled( [ 19 | getPromise( 0, 0, false ), // 0s 20 | getPromise( 1, 2000, false ), // 2s 21 | getPromise( 2, 1000, true ), // 1s (rejects) 22 | ] ); 23 | 24 | // listen to `allPromise` resolution 25 | console.time( 'settled-in' ); 26 | allPromise.then( ( value ) => { 27 | console.log( 'Resolved:', value ); 28 | 29 | value.forEach( result => { 30 | switch( result.status ) { 31 | case 'fulfilled': { 32 | // result: PromiseFulfilledResult 33 | console.log( 'success =>', result.value ); 34 | break; 35 | } 36 | case 'rejected': { 37 | // result: PromiseRejectedResult 38 | console.log( 'error =>', result.reason ); 39 | break; 40 | } 41 | } 42 | } ); 43 | } ).catch( ( error ) => { 44 | // (parameter) error: any 45 | console.log( 'Rejected:', error ); 46 | } ).finally( () => { 47 | console.timeEnd( 'settled-in' ); 48 | } ); -------------------------------------------------------------------------------- /promises-and-async-await/promise-all.ts: -------------------------------------------------------------------------------- 1 | // a function that return a delayed promise 2 | const getPromise = ( 3 | value: number, delay: number, fail: boolean 4 | ): Promise => { 5 | return new Promise( ( resolve, reject ) => { 6 | setTimeout( 7 | () => fail ? reject( value ) : resolve( value ), 8 | delay 9 | ); 10 | } ); 11 | }; 12 | 13 | // const allPromise: Promise 14 | const allPromise = Promise.all( [ 15 | getPromise( 0, 0, false ), // 0s 16 | getPromise( 1, 2000, false ), // 2s 17 | getPromise( 2, 1000, false ), // 1s 18 | ] ); 19 | 20 | // listen to `allPromise` resolution 21 | console.time( 'settled-in' ); 22 | allPromise.then( ( value ) => { 23 | // (parameter) value: number[] 24 | console.log( 'Resolved:', value ); 25 | } ).catch( ( error ) => { 26 | // (parameter) error: any 27 | console.log( 'Rejected:', error ); 28 | } ).finally( () => { 29 | console.timeEnd( 'settled-in' ); 30 | } ); -------------------------------------------------------------------------------- /promises-and-async-await/promise-chaining.ts: -------------------------------------------------------------------------------- 1 | // returns a random integer between 0 and 9 2 | const getRandomInt = (): string => { 3 | return ( Math.random() * 10 ).toFixed( 0 ); 4 | }; 5 | 6 | // resolve with an `even` integer 7 | const findEven = new Promise( ( resolve, reject ) => { 8 | setTimeout( function(): void { 9 | 10 | // convert `string` to `number` 11 | const value = parseInt( getRandomInt() ); 12 | 13 | if( value % 2 === 0 ) { 14 | resolve( value ); 15 | } else { 16 | reject( 'Odd number found!' ); 17 | } 18 | }, 1000 ); 19 | } ); 20 | 21 | // listen to promise resolution 22 | findEven.then( ( value ) => { 23 | // (parameter) value: number 24 | console.log( 'Resolved-1:', value + 1 ); 25 | return `${ value + 1 }`; 26 | } ).then( ( value ) => { 27 | // (parameter) value: string 28 | console.log( 'Resolved-2:', value + 1 ); 29 | } ).catch( ( error ) => {Promise.any 30 | dddPromise.resolve 31 | // (parameter) error: any 32 | console.log( 'Rejected:', error ); 33 | } ).finally( () => { 34 | console.log( 'Completed!' ); 35 | } ); -------------------------------------------------------------------------------- /promises-and-async-await/promise-race.ts: -------------------------------------------------------------------------------- 1 | // a function that return a delayed promise 2 | const getPromise = ( 3 | value: number, delay: number, fail: boolean 4 | ): Promise => { 5 | return new Promise( ( resolve, reject ) => { 6 | setTimeout( 7 | () => fail ? reject( value ) : resolve( value ), 8 | delay 9 | ); 10 | } ); 11 | }; 12 | 13 | // const fastestPromise: Promise 14 | const fastestPromise = Promise.race( [ 15 | getPromise( 0, 500, false ), // 0.5s 16 | getPromise( 1, 2000, false ), // 2s 17 | getPromise( 2, 1000, true ), // 1s (rejects) 18 | ] ); 19 | 20 | // listen to `allPromise` resolution 21 | console.time( 'settled-in' ); 22 | fastestPromise.then( ( value ) => { 23 | // (parameter) value: number 24 | console.log( 'Resolved:', value ); 25 | } ).catch( ( error ) => { 26 | // (parameter) error: any 27 | console.log( 'Rejected:', error ); 28 | } ).finally( () => { 29 | console.timeEnd( 'settled-in' ); 30 | } ); -------------------------------------------------------------------------------- /promises-and-async-await/promise-reject.ts: -------------------------------------------------------------------------------- 1 | // create a sample error message 2 | const message = 'Oops! Something went wrong.'; 3 | 4 | // const oopsPromise: Promise 5 | const oopsPromise = Promise.reject( message ); 6 | 7 | // listen to promise resolution 8 | oopsPromise.then( ( value ) => { 9 | // (parameter) value: never 10 | console.log( 'Resolved:', value ); 11 | } ).catch( ( error ) => { 12 | // (parameter) error: any 13 | console.log( 'Rejected:', error ); 14 | } ); -------------------------------------------------------------------------------- /promises-and-async-await/promise-resolve.ts: -------------------------------------------------------------------------------- 1 | // returns a random integer between 0 and 9 2 | const getRandomInt = (): string => { 3 | return ( Math.random() * 10 ).toFixed( 0 ); 4 | }; 5 | 6 | // get random integer of type `number` 7 | const value: number = parseInt( getRandomInt() ); 8 | 9 | // const numPromise: Promise 10 | const numPromise = Promise.resolve( value ); 11 | 12 | // listen to promise resolution 13 | numPromise.then( ( value ) => { 14 | // (parameter) value: number 15 | console.log( 'Resolved:', value + 1 ); 16 | } ).catch( ( error ) => { 17 | // (parameter) error: any 18 | console.log( 'Rejected:', error ); 19 | } ); -------------------------------------------------------------------------------- /promises-and-async-await/promise.ts: -------------------------------------------------------------------------------- 1 | // returns a random integer between 0 and 9 2 | const getRandomInt = (): string => { 3 | return ( Math.random() * 10 ).toFixed( 0 ); 4 | }; 5 | 6 | // resolve with an `even` integer 7 | const findEven = new Promise( ( resolve, reject ) => { 8 | setTimeout( function(): void { 9 | 10 | // convert `string` to `number` 11 | const value = parseInt( getRandomInt() ); 12 | 13 | if( value % 2 === 0 ) { 14 | resolve( value ); 15 | } else { 16 | reject( 'Odd number found!' ); 17 | } 18 | }, 1000 ); 19 | } ); 20 | 21 | // listen to promise resolution 22 | findEven.then( ( value ) => { 23 | // (parameter) value: number 24 | console.log( 'Resolved:', value + 1 ); 25 | } ).catch( ( error ) => { 26 | // (parameter) error: any 27 | console.log( 'Rejected:', error ); 28 | } ).finally( () => { 29 | console.log( 'Completed!' ); 30 | } ); -------------------------------------------------------------------------------- /promises-and-async-await/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "./async-await-try-catch.ts" 4 | ], 5 | "compilerOptions": { 6 | "lib": [ "DOM", "ES2020" ] 7 | } 8 | } -------------------------------------------------------------------------------- /type-system/.gitignore: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /type-system/any-type-guard.ts: -------------------------------------------------------------------------------- 1 | class Student { 2 | constructor( 3 | public name: string, public marks: number 4 | ){ } 5 | 6 | getGrade(): string { 7 | return (this.marks / 10).toFixed( 0 ); 8 | } 9 | } 10 | 11 | class Player { 12 | constructor( 13 | public name: string, public score: number 14 | ){} 15 | 16 | getRank(): string { 17 | return (this.score / 10).toFixed( 0 ); 18 | } 19 | } 20 | 21 | const getPosition = ( person: any ) => { 22 | if( person instanceof Student ) { 23 | // (parameter) person: Student 24 | 25 | console.log( 26 | `${ person.name } =>`, person.getGrade() 27 | ); 28 | } else if( person instanceof Player ) { 29 | // (parameter) person: Player 30 | 31 | console.log( 32 | `${ person.name } =>`, person.getRank() 33 | ); 34 | } 35 | }; 36 | 37 | getPosition( new Student( 'Ross Geller', 82 ) ); 38 | getPosition( new Student( 'Monica Geller', 71 ) ); -------------------------------------------------------------------------------- /type-system/any-type-issues.ts: -------------------------------------------------------------------------------- 1 | // execute the `func` function 2 | let calculate = ( 3 | a: number, b: number, func: any 4 | ): number => { 5 | return func( a, b ); 6 | }; 7 | 8 | // calculate addition of two numbers 9 | console.log( 10 | "valid =>", 11 | calculate( 12 | 1, 13 | 2, 14 | ( a: number, b: number ) => a + b 15 | ) 16 | ); 17 | 18 | // calculate subtrations of two numbers 19 | console.log( 20 | "invalid =>", 21 | calculate( 1, 2, undefined ) 22 | ); -------------------------------------------------------------------------------- /type-system/declare-keyword.ts: -------------------------------------------------------------------------------- 1 | // declare Lodash interface 2 | interface Lodash { 3 | tail( values: any[] ): any[] 4 | } 5 | 6 | // declare `_` constant of type `Lodash` 7 | declare const _: Lodash; 8 | 9 | // works in runtime 10 | const result = _.tail( [ 1, 2, 3 ] ); -------------------------------------------------------------------------------- /type-system/intersection-common-properties.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | name: string; 3 | gender: string; 4 | } 5 | 6 | interface Player { 7 | score: number; 8 | gender: number; 9 | } 10 | 11 | // get student info 12 | let getStudent = (): Person & Player => { 13 | return { 14 | name: 'Ross Geller', 15 | score: 98, 16 | gender: 'Male' // Type 'string' is not assignable to type 'never'. 17 | }; 18 | }; -------------------------------------------------------------------------------- /type-system/intersection.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | firstName: string; 3 | lastName: string; 4 | } 5 | 6 | interface Player { 7 | score: number; 8 | } 9 | 10 | interface Student { 11 | marks: number; 12 | } 13 | 14 | /*------*/ 15 | 16 | // get student info 17 | let getStudent = ( p: Person, s: Student ): Person & Student => { 18 | return { 19 | firstName: p.firstName, 20 | lastName: p.lastName, 21 | marks: s.marks 22 | }; 23 | }; 24 | 25 | console.log( 'getStudent() =>', getStudent( 26 | { firstName:'Monica', lastName:'Geller' }, // Person 27 | { marks: 100 }, // Student 28 | ) ); 29 | 30 | /*------*/ 31 | 32 | // create a player info 33 | let playerInfo: Person & Player = { 34 | firstName: 'Ross', 35 | lastName: 'Geller', 36 | score: 98 37 | }; 38 | 39 | console.log( 'playerInfo =>', playerInfo ); -------------------------------------------------------------------------------- /type-system/script-vs-module/module/main.ts: -------------------------------------------------------------------------------- 1 | import { sayHello } from './vendor'; 2 | 3 | export interface Person { 4 | firstName: string; 5 | lastName: string; 6 | } 7 | 8 | var ross: Person = { 9 | firstName: 'Ross', 10 | lastName: 'Geller' 11 | }; 12 | 13 | var fullname: string = sayHello( ross ); 14 | console.log( window.prefix ); -------------------------------------------------------------------------------- /type-system/script-vs-module/module/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "./main.ts", 4 | "./vendor.ts", 5 | ], 6 | "compilerOptions": { 7 | "outDir": "dist" 8 | } 9 | } -------------------------------------------------------------------------------- /type-system/script-vs-module/module/vendor.ts: -------------------------------------------------------------------------------- 1 | import { Person } from './main'; 2 | 3 | declare global { 4 | var prefix: string; 5 | } 6 | 7 | var prefix: string = 'Hello, '; 8 | window.prefix = prefix; 9 | 10 | export function sayHello( person: Person ): string { 11 | var result = prefix + person.firstName; 12 | return result; 13 | } -------------------------------------------------------------------------------- /type-system/script-vs-module/script/main.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | firstName: string; 3 | lastName: string; 4 | } 5 | 6 | var ross: Person = { 7 | firstName: 'Ross', 8 | lastName: 'Geller' 9 | }; 10 | var fullname: string = sayHello( ross ); 11 | 12 | export {} -------------------------------------------------------------------------------- /type-system/script-vs-module/script/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "./main.ts", 4 | "./vendor.ts", 5 | ], 6 | "compilerOptions": { 7 | "outDir": "dist" 8 | } 9 | } -------------------------------------------------------------------------------- /type-system/script-vs-module/script/vendor.ts: -------------------------------------------------------------------------------- 1 | var prefix: string = 'Hello, '; 2 | 3 | function sayHello( person: Person ): string { 4 | var result = prefix + person.firstName; 5 | return result; 6 | } 7 | 8 | export {} -------------------------------------------------------------------------------- /type-system/structural-subtyping.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | firstName: string; 3 | lastName: string; 4 | } 5 | 6 | // accept an argument of type `Person 7 | let printPerson = ( person: Person ): void => { 8 | console.log( `Hello, ${ person.firstName } ${ person.lastName }.` ); 9 | }; 10 | 11 | // legal 12 | let ross = { firstName: 'Ross', lastName: 'Geller', gender: 'Male' }; 13 | printPerson( ross ); 14 | 15 | // illegal 16 | // Object literal may only specify known properties, and 'gender' does not exist in type 'Person'. 17 | printPerson( { firstName: 'Ross', lastName: 'Geller', gender: 'Male' } ); 18 | 19 | // legal 20 | let monica: Person; 21 | let monana = { firstName: 'Monica', lastName: 'Geller', gender: 'Male' }; 22 | monica = monana; 23 | 24 | // illegal 25 | // Error: Object literal may only specify known properties, and 'gender' does not exist in type 'Person'. 26 | let p: Person = { firstName: 'Ross', lastName: 'Geller', gender: 'Male' }; -------------------------------------------------------------------------------- /type-system/structural-typing-interfaces.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | firstName: string; 3 | lastName: string; 4 | } 5 | 6 | interface Student { 7 | firstName: string; 8 | lastName: string; 9 | marks: number; 10 | } 11 | 12 | // print fullname of a `Person` object 13 | function getFullName( p: Person ): string { 14 | return `${ p.firstName } ${ p.lastName }`; 15 | } 16 | 17 | var ross: Person = { 18 | firstName: 'Ross', 19 | lastName: 'Geller' 20 | }; 21 | 22 | var monica: Student = { 23 | firstName: 'Monica', 24 | lastName: 'Geller', 25 | marks: 84, 26 | }; 27 | 28 | console.log( 'Ross =>', getFullName( ross ) ); 29 | console.log( 'Monica =>', getFullName( monica ) ); -------------------------------------------------------------------------------- /type-system/structural-typing.ts: -------------------------------------------------------------------------------- 1 | class Person { 2 | constructor( 3 | public firstName: string, 4 | public lastName: string 5 | ) {} 6 | } 7 | 8 | class Student { 9 | constructor( 10 | public firstName: string, 11 | public lastName: string, 12 | public marks: number 13 | ) {} 14 | } 15 | 16 | // print fullname of a `Person` object 17 | function getFullName( p: Person ): string { 18 | return `${ p.firstName } ${ p.lastName }`; 19 | } 20 | 21 | var ross = new Person( 'Ross', 'Geller' ); 22 | var monica = new Student( 'Monica', 'Geller', 84 ); 23 | 24 | console.log( 'Ross =>', getFullName( ross ) ); 25 | console.log( 'Monica =>', getFullName( monica ) ); -------------------------------------------------------------------------------- /type-system/type-assertion-correct.ts: -------------------------------------------------------------------------------- 1 | // return a value 2 | let getStuff = ( type: string ): any => { 3 | switch( type ) { 4 | case 'string': return 'Apple'; 5 | case 'number': return 3.1415926; 6 | case 'boolean': return false; 7 | } 8 | } 9 | 10 | // get some values 11 | let apple = getStuff( 'string' ); 12 | let pi = getStuff( 'number' ); 13 | let isApplePie = getStuff( 'boolean' ) as boolean; 14 | 15 | 16 | // Compilation Error: Property 'toFixed' does not exist on type 'string'. 17 | console.log( ( apple as string ).toFixed() ); 18 | 19 | // Compilation Error: Property 'toUpperCase' does not exist on type 'number'. 20 | console.log( ( pi ).toUpperCase( 2 ) ); 21 | 22 | // Compilation Error: Operator '+' cannot be applied to types 'boolean' and 'number'. 23 | console.log( isApplePie + 1 ); -------------------------------------------------------------------------------- /type-system/type-assertion-incorrect.ts: -------------------------------------------------------------------------------- 1 | // return a value 2 | let getStuff = ( type: string ): any => { 3 | switch( type ) { 4 | case 'string': return 'Apple'; 5 | case 'number': return 3.1415926; 6 | case 'boolean': return false; 7 | } 8 | } 9 | 10 | // get some values 11 | let apple = getStuff( 'string' ); 12 | let pi = getStuff( 'number' ); 13 | let isApplePie = getStuff( 'boolean' ); 14 | 15 | // let apple: any 16 | console.log( apple.toFixed( 2 ) ); 17 | // 🔴 TypeError: apple.toFixed is not a function 18 | 19 | // let pi: any 20 | console.log( pi.toUpperCase( 2 ) ); 21 | // 🔴 TypeError: pi.toUpperCase is not a function 22 | 23 | // let isApplePie: any 24 | console.log( isApplePie + 1 ); -------------------------------------------------------------------------------- /type-system/type-assertion.ts: -------------------------------------------------------------------------------- 1 | let getStuff = ( type: string ): any => { 2 | switch( type ) { 3 | case 'fruit': return 'Apple'; 4 | case 'year': return 2012; 5 | case 'truth': return false; 6 | } 7 | } 8 | 9 | let stuff = getStuff( 'fruit' ); 10 | console.log( stuff.toUpperCase() ); -------------------------------------------------------------------------------- /type-system/type-guard-in-operator.ts: -------------------------------------------------------------------------------- 1 | // some interfaces 2 | interface Student { name: string; marks: number; } 3 | interface Player { name: string; score: number; } 4 | interface Racer { name: string; points: number; } 5 | 6 | // this function prints info 7 | let printInfo = ( person: Student | Player | Racer ): void => { 8 | if( 'marks' in person ) { 9 | // (parameter) person: Student 10 | console.log( 11 | `${ person.name } received ${ person.marks } marks.` 12 | ); 13 | } else if( 'score' in person ) { 14 | // (parameter) person: Player 15 | console.log( 16 | `${ person.name } scored ${ person.score }.` 17 | ); 18 | } else { 19 | // (parameter) person: Racer 20 | console.log( 21 | `${ person.name } gained ${ person.points } points.` 22 | ); 23 | } 24 | }; 25 | 26 | printInfo( { name: 'Ross Geller', marks: 98 } ); 27 | printInfo( { name: 'Monica Geller', score: 100 } ); 28 | printInfo( { name: 'Rachel Green', points: 100 } ); -------------------------------------------------------------------------------- /type-system/type-guard-instanceof.ts: -------------------------------------------------------------------------------- 1 | class Student { 2 | constructor( 3 | public name: string, private marks: number 4 | ) {} 5 | 6 | getMarks() { return this.marks; } 7 | } 8 | 9 | class Player { 10 | constructor( 11 | public name: string, private score: number 12 | ) {} 13 | 14 | getScore(){ return this.score; } 15 | } 16 | 17 | // this function prints info 18 | let printInfo = ( person: Student | Player ): void => { 19 | if( person instanceof Student ) { 20 | // (parameter) person: Student 21 | 22 | console.log( 23 | `${ person.name }: ${ person.getMarks() }` 24 | ); 25 | } else { 26 | // (parameter) person: Player 27 | 28 | console.log( 29 | `${ person.name }: ${ person.getScore() }` 30 | ); 31 | } 32 | }; 33 | 34 | printInfo( new Student( 'Ross Geller', 98 ) ); 35 | printInfo( new Player( 'Monica Geller', 100 ) ); -------------------------------------------------------------------------------- /type-system/type-guard-typeof-function.ts: -------------------------------------------------------------------------------- 1 | // this function prints marks 2 | let printMarks = ( marks: number | string ): void => { 3 | if( typeof marks === 'string' ) { 4 | // (parameter) marks: string 5 | 6 | const value = marks.toUpperCase(); // legal 7 | console.log( `MARKS: ${ value } grade` ); 8 | } else { 9 | // (parameter) marks: number 10 | 11 | const value = marks.toFixed( 0 ); // legal 12 | console.log( `MARKS: ${ value } out of 10.` ); 13 | } 14 | }; 15 | 16 | // print marks 17 | printMarks( 'b' ); 18 | printMarks( 8.621 ); -------------------------------------------------------------------------------- /type-system/type-guard-typeof-property.ts: -------------------------------------------------------------------------------- 1 | interface Student { 2 | name: string; 3 | marks: number | string; 4 | } 5 | 6 | // this function prints info 7 | let printInfo = ( person: Student ): void => { 8 | if( typeof person.marks === 'string' ) { 9 | // (property) Student.marks: string 10 | 11 | const name = person.name; 12 | const value = person.marks.toUpperCase(); 13 | console.log( `${ name } -> ${ value } grade.` ); 14 | } else { 15 | // (property) Student.marks: number 16 | 17 | const name = person.name; 18 | const value = person.marks.toFixed( 0 ); 19 | console.log( `${ name } -> ${ value }/10.` ); 20 | } 21 | }; 22 | 23 | // print info 24 | printInfo( { name: 'Ross Geller', marks: 'b' } ); 25 | printInfo( { name: 'Monica Geller', marks: 8.621 } ); -------------------------------------------------------------------------------- /type-system/type-guard-user-defined.ts: -------------------------------------------------------------------------------- 1 | // type predicate function 2 | let predicateString = ( 3 | arg: number | string 4 | ): arg is string => { 5 | return typeof arg === 'string'; 6 | } 7 | 8 | // this function prints marks 9 | let printMarks = ( marks: number | string ): void => { 10 | if( predicateString( marks ) ) { 11 | // (parameter) marks: string 12 | 13 | const value = marks.toUpperCase(); // legal 14 | console.log( `MARKS: ${ value } grade` ); 15 | } else { 16 | // (parameter) marks: number 17 | 18 | const value = marks.toFixed( 0 ); // legal 19 | console.log( `MARKS: ${ value } out of 10.` ); 20 | } 21 | }; 22 | 23 | // print marks 24 | printMarks( 'b' ); 25 | printMarks( 8.621 ); -------------------------------------------------------------------------------- /type-system/type-inference.ts: -------------------------------------------------------------------------------- 1 | let b = true; // let b: boolean 2 | let n = 1; // let n: number 3 | let s = "Hello World"; // let s: string 4 | let o = { name: 'Ross geller' }; // let o: { name: string; } 5 | let f = ( a = 1 ) => a + 1; // let f: (a?: number) => number 6 | let a = [ 1, 2, 3 ]; // let a: number[] -------------------------------------------------------------------------------- /type-system/type-union-gender-correct.ts: -------------------------------------------------------------------------------- 1 | // define function to set gender 2 | let setGender = ( gender: 'male' | 'female' | 'other' ): void => { 3 | // set gender 4 | // ... 5 | }; 6 | 7 | // call `setGender` function with wrong gender value 8 | setGender( 'true' ); -------------------------------------------------------------------------------- /type-system/type-union-gender-incorrect.ts: -------------------------------------------------------------------------------- 1 | // define function to set gender 2 | let setGender = ( gender: string ): void | never => { 3 | if( gender !== 'male' && gender !== 'female' && gender !== 'other' ) { 4 | throw new Error( 'Please provide a correct gender.' ); 5 | } 6 | 7 | // set gender 8 | // .... 9 | }; 10 | 11 | // call `setGender` function with wrong gender value 12 | setGender( 'true' ); -------------------------------------------------------------------------------- /type-system/type-union-keyof.ts: -------------------------------------------------------------------------------- 1 | // `Person` interface 2 | interface Person { 3 | name: string; 4 | age: number; 5 | } 6 | 7 | // keyof Person => "firstName" | "lastName" | "age" 8 | let printPersonValue = ( p: Person, key: keyof Person ): void => { 9 | // (parameter) p: Person 10 | // (parameter) key: "name" | "age" 11 | 12 | console.log( p[ key ] ); 13 | }; 14 | 15 | // legal 16 | printPersonValue( { name: 'Ross Geller', age: 30 }, 'name' ); 17 | 18 | // illegal / Error: Argument of type '"profession"' is not assignable to parameter of type '"name" | "age"' 19 | printPersonValue( { name: 'Monica Geller', age: 30 }, 'profession' ); -------------------------------------------------------------------------------- /type-system/type-union-with-interfaces-discriminated-union.ts: -------------------------------------------------------------------------------- 1 | // `Student` interface 2 | interface Student { 3 | type: 'student'; // discriminant 4 | name: string; 5 | marks: number; 6 | } 7 | 8 | // `Player` interface 9 | interface Player { 10 | type: 'player'; // discriminant 11 | name: string; 12 | score: number; 13 | } 14 | 15 | // this function prints info 16 | let printInfo = ( person: Student | Player ): void => { 17 | switch( person.type ) { 18 | case 'student': { 19 | // (parameter) person: Student 20 | return console.log( 21 | `${ person.name } received ${ person.marks } marks.` 22 | ); 23 | } 24 | case 'player': { 25 | // (parameter) person: Player 26 | return console.log( 27 | `${ person.name } scored ${ person.score }.` 28 | ); 29 | } 30 | } 31 | }; 32 | 33 | // log info of the `Student` and `Player` objects 34 | printInfo( { type: 'student', name: 'Ross Geller', marks: 98 } ); 35 | printInfo( { type: 'player', name: 'Monica Geller', score: 100 } ); -------------------------------------------------------------------------------- /type-system/type-union-with-interfaces-incorrect.ts: -------------------------------------------------------------------------------- 1 | // `Student` interface 2 | interface Student { 3 | name: string; 4 | marks: number; 5 | } 6 | 7 | // `Student` interface 8 | interface Player { 9 | name: string; 10 | score: number; 11 | } 12 | 13 | // this function prints info 14 | let printInfo = ( person: Student | Player ): void => { 15 | // Error: Property 'marks' does not exist on type 'Student | Player'. 16 | // Error: Property 'marks' does not exist on type 'Player'. 17 | console.log( `${ person.name } received ${ person.marks } marks.` ); 18 | }; -------------------------------------------------------------------------------- /type-system/type-union-with-interfaces-type-assertion.ts: -------------------------------------------------------------------------------- 1 | // `Student` interface 2 | interface Student { 3 | name: string; 4 | marks: number; 5 | } 6 | 7 | // `Player` interface 8 | interface Player { 9 | name: string; 10 | score: number; 11 | } 12 | 13 | // this function prints info 14 | let printInfo = ( person: Student | Player ): void => { 15 | console.log( 16 | `${ person.name } received ${ (person as Student).marks } marks.` 17 | ); 18 | }; 19 | 20 | // print info of a `Student` 21 | const ross: Student = { name: 'Ross Geller', marks: 98 }; 22 | printInfo( ross ); -------------------------------------------------------------------------------- /type-system/typeof-keyword.ts: -------------------------------------------------------------------------------- 1 | // create an object 2 | // let ross: { firstName: string; lastName: string; } 3 | let ross = { firstName: 'Ross', lastName: 'Geller' }; 4 | 5 | // `monica` must have a shape of `ross` 6 | let monica: typeof ross = { 7 | firstName: 'Monica', 8 | lastName: 'Geller' 9 | }; 10 | 11 | // create a type alias for reuse 12 | type Person = typeof ross; 13 | 14 | // create `rachel` of type `Person` 15 | let rachel: Person = { 16 | firstName: 'Rachel', 17 | lastName: 'Green' 18 | }; -------------------------------------------------------------------------------- /type-system/unit-type-assertion.ts: -------------------------------------------------------------------------------- 1 | // function that accepts unit type argument 2 | let sayHello = ( prefix: 'Hello', name: string ): void => { 3 | console.log( `${ prefix }, ${ name }.` ); 4 | }; 5 | 6 | // legal: since literal value ('Hello') provided 7 | sayHello( 'Hello', 'Ross Geller' ); 8 | 9 | /*-----------*/ 10 | 11 | // let monicaPrefix: 'Hello' 12 | let monicaPrefix: 'Hello' = 'Hello'; 13 | let monica = 'Monica Geller'; 14 | 15 | // legal: since `monicaPrefix` has type of 'Hello' 16 | sayHello( monicaPrefix, monica ); 17 | 18 | /*-----------*/ 19 | 20 | // let rachelPrefix: string 21 | let rachelPrefix = 'Hello'; 22 | let rachel = 'Rachel Green'; 23 | 24 | // Error: Argument of type 'string' is not assignable to parameter of type ''Hello''. 25 | sayHello( rachelPrefix, rachel ); 26 | 27 | // workaround: legal but misleading 28 | sayHello( (rachelPrefix as 'Hello'), rachel ); -------------------------------------------------------------------------------- /type-system/unit-type-implementation.ts: -------------------------------------------------------------------------------- 1 | // Type: let executeSafe: (task: string) => 0 2 | let executeSafe = ( task: string ): 0 => { 3 | console.log( `executing: ${ task }` ); 4 | return 0; 5 | }; 6 | 7 | // Error: This condition will always return 'false' since the types '1' and '0' have no overlap. 8 | console.log( 1 == executeSafe( 'MY_TASK' ) ); -------------------------------------------------------------------------------- /type-system/unit-type.ts: -------------------------------------------------------------------------------- 1 | // collective types 2 | var str = 'hello'; // var str: string 3 | var num = 100; // var num: number 4 | let bool = false; // let bool: boolean 5 | 6 | // unit (literal) types 7 | const s = "Hello"; // const s: "Hello" 8 | const n = 100; // const n: 100 9 | const b = false; // const b: false -------------------------------------------------------------------------------- /utility-types/extract-exclude.ts: -------------------------------------------------------------------------------- 1 | // union type 2 | type ColorSet = 'green' | 'red' | 'blue' | 4 | (() => string); 3 | 4 | // type GreenSet = "green" 5 | type GreenSet = Extract; 6 | 7 | // type SafeSet = "green" | "blue" 8 | type SafeSet = Extract; 9 | 10 | // type stringSet = "green" | "red" | "blue" 11 | // type ExstringSet = "green" | "red" | "blue" 12 | type stringSet = Extract; 13 | type ExstringSet = Exclude; 14 | 15 | // type FuncSet = () => string 16 | type FuncSet = Extract; 17 | 18 | // type literalSet = "green" | "red" | "blue" | 4 19 | type LiteralSet = Exclude; -------------------------------------------------------------------------------- /utility-types/nonnullable.ts: -------------------------------------------------------------------------------- 1 | type SimpleValue = string | number | null | undefined; 2 | 3 | // type SafeValue = string | number 4 | type SafeValue = NonNullable; 5 | 6 | // using `Exclude` utility type 7 | // type ExSafeValue = string | number 8 | type ExSafeValue = Exclude; -------------------------------------------------------------------------------- /utility-types/partial.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | firstName: string; 3 | lastName: string; 4 | } 5 | 6 | // `p` argument is an interface with optional `firstName` or `lastName` properties 7 | const sayHello = ( p: Partial ): void => { 8 | if( ! p.firstName ) { 9 | console.log( 10 | `Hello, Dear ${ p.lastName }.` 11 | ); 12 | } else if( ! p.lastName ) { 13 | console.log( 14 | `Hello, Mr./Ms. ${ p.firstName }.` 15 | ); 16 | } else { 17 | console.log( 18 | `Hello, ${ p.firstName } ${ p.lastName }.` 19 | ); 20 | } 21 | } 22 | 23 | sayHello( { firstName: 'Ross', lastName: 'Geller' } ); 24 | sayHello( { firstName: 'Monica' } ); 25 | sayHello( { lastName: 'Tribbiani' } ); -------------------------------------------------------------------------------- /utility-types/pick-omit.ts: -------------------------------------------------------------------------------- 1 | interface Student { 2 | firstName: string; 3 | lastName: string; 4 | marks: number; 5 | } 6 | 7 | // create a `Person` interface by picking properties 8 | // type Person = { firstName: string; lastName: string; } 9 | type Person = Pick; 10 | let ross: Person = { 11 | firstName: 'Ross', 12 | lastName: 'Geller', 13 | }; 14 | 15 | // create a `Human` interface by omitting a property 16 | // type Human = { firstName: string; lastName: string; } 17 | type Human = Omit; 18 | let monica: Human = { 19 | firstName: 'Monica', 20 | lastName: 'Geller' 21 | }; -------------------------------------------------------------------------------- /utility-types/readonly.js: -------------------------------------------------------------------------------- 1 | // changes `firstName` and `lastName` 2 | var changeName = function (person, firstName, lastName) { 3 | // Error: Cannot assign to 'firstName' because it is a read-only property. 4 | person.firstName = firstName; 5 | // Error: Cannot assign to 'lastName' because it is a read-only property. 6 | person.lastName = lastName; 7 | return person; 8 | }; 9 | // create a `Person` object 10 | var phoebe = { 11 | firstName: 'Phoebe', 12 | lastName: 'Buffay' 13 | }; 14 | // change `phoebe` property values 15 | changeName(phoebe, 'Regina', 'Phalange'); 16 | -------------------------------------------------------------------------------- /utility-types/readonly.ts: -------------------------------------------------------------------------------- 1 | interface Person { 2 | firstName: string; 3 | lastName: string; 4 | } 5 | 6 | // changes `firstName` and `lastName` 7 | const changeName = ( 8 | person: Readonly, 9 | firstName: string, 10 | lastName: string, 11 | ): Person => { 12 | // Error: Cannot assign to 'firstName' because it is a read-only property. 13 | person.firstName = firstName; 14 | 15 | // Error: Cannot assign to 'lastName' because it is a read-only property. 16 | person.lastName = lastName; 17 | 18 | return person; 19 | } 20 | 21 | // create a `Person` object 22 | const phoebe: Person = { 23 | firstName: 'Phoebe', 24 | lastName: 'Buffay' 25 | }; 26 | 27 | // change `phoebe` property values 28 | changeName( phoebe, 'Regina', 'Phalange' ); -------------------------------------------------------------------------------- /utility-types/record.ts: -------------------------------------------------------------------------------- 1 | // union of unit types (keys) 2 | type keys = 'firstName' | 'lastName'; 3 | 4 | // create an interface from `keys` type 5 | type Person = Record 6 | 7 | // print names in uppercase 8 | const sayHello = ( p: Person ): void => { 9 | // first name uppercase 10 | console.log( 11 | 'FIRST_NAME:', p.firstName.toUpperCase() 12 | ); 13 | 14 | // last name uppercase 15 | console.log( 16 | 'LAST_NAME:', p.lastName.toUpperCase() 17 | ); 18 | } 19 | 20 | // create an object of type `Person` 21 | const ross: Person = { 22 | firstName: 'Ross', 23 | lastName: 'Geller', 24 | }; 25 | 26 | sayHello( ross ); -------------------------------------------------------------------------------- /webpack-setup/dist/main.js: -------------------------------------------------------------------------------- 1 | !function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t);var r=new(function(){function e(e,t){this.fname=e,this.lname=t}return e.prototype.getFullName=function(){return this.fname+" "+this.lname},e}())("John","Doe");console.log(r.getFullName())}]); 2 | //# sourceMappingURL=main.js.map -------------------------------------------------------------------------------- /webpack-setup/dist/main.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/lib/classes.ts","webpack:///./src/index.ts"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","person","fname","lname","this","getFullName","console","log"],"mappings":"aACE,IAAIA,EAAmB,GAGvB,SAASC,EAAoBC,GAG5B,GAAGF,EAAiBE,GACnB,OAAOF,EAAiBE,GAAUC,QAGnC,IAAIC,EAASJ,EAAiBE,GAAY,CACzCG,EAAGH,EACHI,GAAG,EACHH,QAAS,IAUV,OANAI,EAAQL,GAAUM,KAAKJ,EAAOD,QAASC,EAAQA,EAAOD,QAASF,GAG/DG,EAAOE,GAAI,EAGJF,EAAOD,QAKfF,EAAoBQ,EAAIF,EAGxBN,EAAoBS,EAAIV,EAGxBC,EAAoBU,EAAI,SAASR,EAASS,EAAMC,GAC3CZ,EAAoBa,EAAEX,EAASS,IAClCG,OAAOC,eAAeb,EAASS,EAAM,CAAEK,YAAY,EAAMC,IAAKL,KAKhEZ,EAAoBkB,EAAI,SAAShB,GACX,oBAAXiB,QAA0BA,OAAOC,aAC1CN,OAAOC,eAAeb,EAASiB,OAAOC,YAAa,CAAEC,MAAO,WAE7DP,OAAOC,eAAeb,EAAS,aAAc,CAAEmB,OAAO,KAQvDrB,EAAoBsB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQrB,EAAoBqB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,iBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKX,OAAOY,OAAO,MAGvB,GAFA1B,EAAoBkB,EAAEO,GACtBX,OAAOC,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOrB,EAAoBU,EAAEe,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,IAAQC,KAAK,KAAMD,IAC9I,OAAOF,GAIRzB,EAAoB6B,EAAI,SAAS1B,GAChC,IAAIS,EAAST,GAAUA,EAAOqB,WAC7B,WAAwB,OAAOrB,EAAgB,SAC/C,WAA8B,OAAOA,GAEtC,OADAH,EAAoBU,EAAEE,EAAQ,IAAKA,GAC5BA,GAIRZ,EAAoBa,EAAI,SAASiB,EAAQC,GAAY,OAAOjB,OAAOkB,UAAUC,eAAe1B,KAAKuB,EAAQC,IAGzG/B,EAAoBkC,EAAI,GAIjBlC,EAAoBA,EAAoBmC,EAAI,G,sCClFrD,ICGMC,EAAiB,IDHvB,WAII,WAAYC,EAAeC,GACvBC,KAAKF,MAAQA,EACbE,KAAKD,MAAQA,EAMrB,OAHI,YAAAE,YAAA,WACI,OAAWD,KAAKF,MAAK,IAAME,KAAKD,OAExC,EAZA,GCGuB,CAAY,OAAQ,OAC3CG,QAAQC,IAAKN,EAAOI","file":"main.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","export class Person {\n private fname: string;\n private lname: string;\n\n constructor(fname: string, lname: string) {\n this.fname = fname;\n this.lname = lname;\n }\n\n getFullName(): string {\n return `${ this.fname } ${ this.lname }`;\n }\n}","import { Person } from './lib/classes';\n\n// create a `Person` instance\nconst person: Person = new Person( 'John', 'Doe' );\nconsole.log( person.getFullName() );"],"sourceRoot":""} -------------------------------------------------------------------------------- /webpack-setup/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | TypeScript 6 | 7 | 8 | 9 | 10 |

Hello World!

11 | 12 | -------------------------------------------------------------------------------- /webpack-setup/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webpack-setup", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "dist/main.js", 6 | "dependencies": {}, 7 | "devDependencies": { 8 | "fork-ts-checker-webpack-plugin": "^5.2.0", 9 | "ts-loader": "^8.0.3", 10 | "typescript": "^4.0.2", 11 | "webpack": "^4.44.1", 12 | "webpack-cli": "^3.3.12" 13 | }, 14 | "scripts": { 15 | "build": "webpack" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /webpack-setup/src/index.ts: -------------------------------------------------------------------------------- 1 | import { Person } from './lib/classes'; 2 | 3 | // create a `Person` instance 4 | const person: Person = new Person( 'John', 'Doe' ); 5 | console.log( person.getFullName() ); -------------------------------------------------------------------------------- /webpack-setup/src/lib/classes.ts: -------------------------------------------------------------------------------- 1 | export class Person { 2 | private fname: string; 3 | private lname: string; 4 | 5 | constructor(fname: string, lname: string) { 6 | this.fname = fname; 7 | this.lname = lname; 8 | } 9 | 10 | getFullName(): string { 11 | return `${ this.fname } ${ this.lname }`; 12 | } 13 | } -------------------------------------------------------------------------------- /webpack-setup/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noImplicitAny": true, 4 | "target": "ES5", 5 | "module": "ES2015", 6 | "sourceMap": true, 7 | "importsNotUsedAsValues": "preserve" 8 | } 9 | } -------------------------------------------------------------------------------- /webpack-setup/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require( 'path' ); 2 | const ForkTsCheckerWebpackPlugin = require( 'fork-ts-checker-webpack-plugin' ); 3 | 4 | module.exports = { 5 | 6 | // generate source maps 7 | devtool: 'source-map', 8 | 9 | // bundling mode 10 | mode: 'production', 11 | 12 | // entry files 13 | entry: './src/index.ts', 14 | 15 | // output bundles (location) 16 | output: { 17 | path: path.resolve( __dirname, 'dist' ), 18 | filename: 'main.js', 19 | }, 20 | 21 | // file resolutions 22 | resolve: { 23 | extensions: [ '.ts', '.js' ], 24 | }, 25 | 26 | // loaders 27 | module: { 28 | rules: [ 29 | { 30 | test: /\.tsx?/, 31 | use: { 32 | loader: 'ts-loader', 33 | options: { 34 | transpileOnly: true, 35 | } 36 | }, 37 | exclude: /node_modules/, 38 | } 39 | ] 40 | }, 41 | 42 | // plugins 43 | plugins: [ 44 | new ForkTsCheckerWebpackPlugin(), // run TSC on a separate thread 45 | ], 46 | 47 | // set watch mode to `true` 48 | watch: true 49 | }; 50 | --------------------------------------------------------------------------------