├── .gitignore ├── index.html ├── package-lock.json ├── package.json ├── src ├── app.ts ├── decorators.ts ├── form-namespace.ts ├── generic.ts └── namespaces.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | dist 4 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | TypeScript 10 | 11 | 12 | 13 | 14 |
15 | 16 |
17 | 18 |
19 |
20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts-advanced", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "typescript": { 8 | "version": "3.7.3", 9 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.3.tgz", 10 | "integrity": "sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==", 11 | "dev": true 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts-advanced", 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 | "typescript": "^3.7.3" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/app.ts: -------------------------------------------------------------------------------- 1 | // http://www.typescriptlang.org/docs/handbook/compiler-options.html#compiler-options 2 | 3 | class Person { 4 | constructor(private name: string) {} 5 | } 6 | 7 | const max = new Person('Maxim') 8 | 9 | // Demo comment 10 | 11 | // const btn = document.querySelector('#btn')! 12 | // 13 | // btn.addEventListener('click', () => { 14 | // console.log('Btn clicked!') 15 | // }) 16 | 17 | // ======= 18 | 19 | let anyFlag 20 | 21 | const globalVar = 'Message' 22 | 23 | function logInfo(data: string, _?: number) { 24 | // const message = 'String' 25 | console.log(data) 26 | anyFlag = true 27 | console.log(anyFlag) 28 | } 29 | 30 | logInfo('I am log string') 31 | 32 | function multiple(a: number, b: number) { 33 | if (a && b) { 34 | return a * b 35 | } 36 | return 37 | } 38 | -------------------------------------------------------------------------------- /src/decorators.ts: -------------------------------------------------------------------------------- 1 | // function Log(constructor: Function) { 2 | // console.log(constructor) 3 | // } 4 | // 5 | // function Log2(target: any, propName: string | Symbol) { 6 | // console.log(target) 7 | // console.log(propName) 8 | // } 9 | // 10 | // function Log3(target: any, propName: string | Symbol, descriptor: PropertyDescriptor) { 11 | // console.log(target) 12 | // console.log(propName) 13 | // console.log(descriptor) 14 | // } 15 | 16 | // interface ComponentDecorator { 17 | // selector: string 18 | // template: string 19 | // } 20 | // 21 | // function Component(config: ComponentDecorator) { 22 | // return function 23 | // 24 | // (Constructor: T) { 25 | // return class extends Constructor { 26 | // constructor(...args: any[]) { 27 | // super(...args) 28 | // 29 | // const el = document.querySelector(config.selector)! 30 | // el.innerHTML = config.template 31 | // } 32 | // } 33 | // } 34 | // } 35 | // 36 | // function Bind(_: any, _2: any, descriptor: PropertyDescriptor): PropertyDescriptor { 37 | // const original = descriptor.value 38 | // 39 | // return { 40 | // configurable: true, 41 | // enumerable: false, 42 | // get() { 43 | // return original.bind(this) 44 | // } 45 | // } 46 | // } 47 | // 48 | // @Component({ 49 | // selector: '#card', 50 | // template: ` 51 | //
52 | //
53 | // Card Component 54 | //
55 | //
56 | // ` 57 | // }) 58 | // class CardComponent { 59 | // constructor(public name: string) { 60 | // } 61 | // 62 | // @Bind 63 | // logName(): void { 64 | // console.log(`Component Name: ${this.name}`) 65 | // } 66 | // } 67 | // 68 | // const card = new CardComponent('My Card Component') 69 | // 70 | // const btn = document.querySelector('#btn')! 71 | // 72 | // btn.addEventListener('click', card.logName) 73 | 74 | // ================ 75 | 76 | type ValidatorType = 'required' | 'email' 77 | 78 | interface ValidatorConfig { 79 | [prop: string]: { 80 | [validateProp: string]: ValidatorType 81 | } 82 | } 83 | 84 | const validators: ValidatorConfig = {} 85 | 86 | function Required(target: any, propName: string) { 87 | validators[target.constructor.name] = { 88 | ...validators[target.constructor.name], 89 | [propName]: 'required' 90 | } 91 | } 92 | 93 | function validate(obj: any): boolean { 94 | const objConfig = validators[obj.constructor.name] 95 | if (!objConfig) { 96 | return true 97 | } 98 | let isValid = true 99 | Object.keys(objConfig).forEach(key => { 100 | if (objConfig[key] === 'required') { 101 | isValid = isValid && !!obj[key] 102 | } 103 | }) 104 | return isValid 105 | } 106 | 107 | // class Form { 108 | // @Required 109 | // public email: string | void 110 | // 111 | // constructor(email?: string) { 112 | // this.email = email 113 | // } 114 | // } 115 | // 116 | // const form = new Form('v@mail.ru') 117 | // 118 | // if (validate(form)) { 119 | // console.log('Valid: ', form) 120 | // } else { 121 | // console.log('Validation Error') 122 | // } 123 | // 124 | -------------------------------------------------------------------------------- /src/form-namespace.ts: -------------------------------------------------------------------------------- 1 | namespace Form { 2 | export type FormType = 'inline' | 'block' 3 | export type FormState = 'active' | 'disabled' 4 | 5 | export interface FormInfo { 6 | type: FormType 7 | state: FormState 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/generic.ts: -------------------------------------------------------------------------------- 1 | // const cars: string[] = ['Ford', 'Audi'] 2 | // const cars2: Array = ['Ford', 'Audi'] 3 | 4 | // const promise: Promise = new Promise(resolve => { 5 | // setTimeout(() => { 6 | // resolve(42) 7 | // }, 2000) 8 | // }) 9 | // 10 | // promise.then(data => { 11 | // console.log(data.toFixed()) 12 | // }) 13 | 14 | function mergeObjects(a: T, b: R) { 15 | return Object.assign({}, a, b) 16 | } 17 | 18 | const merged = mergeObjects({name: 'Vladilen'}, {age: 26}) 19 | const merged2 = mergeObjects({model: 'Ford'}, {year: 2010}) 20 | 21 | // const merged3 = mergeObjects({a: 1}, 'bbb') 22 | // console.log(merged3) 23 | 24 | // ================= 25 | 26 | interface ILength { 27 | length: number 28 | } 29 | 30 | function withCount(value: T): {value: T, count: string} { 31 | return { 32 | value, 33 | count: `В этом объекте ${value.length} символов` 34 | } 35 | } 36 | 37 | // console.log(withCount('Привет typescript')) 38 | // console.log(withCount(['I', 'Am', 'Array'])) 39 | // console.log(withCount(20)) 40 | // console.log(withCount({length: 20})) 41 | 42 | // ============== 43 | 44 | // function getObjectValue(obj: T, key: R) { 45 | // return obj[key] 46 | // } 47 | // 48 | // const person = { 49 | // name: 'Vladilen', 50 | // age: 26, 51 | // job: 'Javascript' 52 | // } 53 | // console.log(getObjectValue(person, 'name')) 54 | // console.log(getObjectValue(person, 'age')) 55 | // console.log(getObjectValue(person, 'job')) 56 | 57 | // =============== 58 | 59 | class Collection { 60 | constructor(private _items: T[] = []) {} 61 | 62 | add(item: T) { 63 | this._items.push(item) 64 | } 65 | 66 | remove(item: T) { 67 | this._items = this._items.filter(i => i !== item) 68 | } 69 | 70 | get items(): T[] { 71 | return this._items 72 | } 73 | } 74 | 75 | // const strings = new Collection(['I', 'Am', 'Strings']) 76 | // strings.add('!') 77 | // strings.remove('Am') 78 | // console.log(strings.items) 79 | // 80 | // const numbers = new Collection([1, 2, 3]) 81 | // numbers.add(2) 82 | // numbers.remove(3) 83 | // console.log(numbers.items) 84 | 85 | // const objs = new Collection([{a: 1}, {b: 2}]) 86 | // // objs.remove({b: 2}) 87 | // // console.log(objs.items) 88 | 89 | // =============== 90 | 91 | interface Car { 92 | model: string 93 | year: number 94 | } 95 | 96 | function createAndValidateCar(model: string, year: number): Car { 97 | const car: Partial = {} 98 | 99 | if (model.length > 3) { 100 | car.model = model 101 | } 102 | 103 | if (year > 2000) { 104 | car.year = year 105 | } 106 | 107 | return car as Car 108 | } 109 | 110 | /// 111 | 112 | const cars: Readonly> = ['Ford', 'Audi'] 113 | // cars.shift() 114 | // cars[1] 115 | 116 | const ford: Readonly = { 117 | model: 'Ford', 118 | year: 2020 119 | } 120 | 121 | // ford.model = 'Ferrari' 122 | 123 | -------------------------------------------------------------------------------- /src/namespaces.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | namespace Form { 4 | class MyForm { 5 | private type: FormType = 'inline' 6 | private state: FormState = 'active' 7 | 8 | constructor(public email: string) { 9 | } 10 | 11 | getInfo(): FormInfo { 12 | return { 13 | type: this.type, 14 | state: this.state 15 | } 16 | } 17 | } 18 | 19 | export const myForm = new MyForm('v@mail.ru') 20 | } 21 | 22 | console.log(Form.myForm) 23 | 24 | // console.log(myForm) 25 | 26 | 27 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | // "incremental": true, /* Enable incremental compilation */ 5 | "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ 6 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 7 | // "lib": ["dom", "scripthost", "dom.iterable", "es2016"], /* Specify library files to be included in the compilation. */ 8 | // "allowJs": true, /* Allow javascript files to be compiled. */ 9 | // "checkJs": true, /* Report errors in .js files. */ 10 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 11 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 12 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 13 | "sourceMap": true, /* Generates corresponding '.map' file. */ 14 | // "outFile": "./", /* Concatenate and emit output to single file. */ 15 | "outDir": "./dist", /* Redirect output structure to the directory. */ 16 | "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 17 | // "composite": true, /* Enable project compilation */ 18 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 19 | "removeComments": true, /* Do not emit comments to output. */ 20 | // "noEmit": true, /* Do not emit outputs. */ 21 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 22 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 23 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 24 | "noEmitOnError": true, 25 | 26 | /* Strict Type-Checking Options */ 27 | "strict": true, /* Enable all strict type-checking options. */ 28 | "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 29 | "strictNullChecks": true, /* Enable strict null checks. */ 30 | "strictFunctionTypes": true, /* Enable strict checking of function types. */ 31 | "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 32 | "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 33 | "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 34 | "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 35 | 36 | /* Additional Checks */ 37 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 38 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 39 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 40 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 41 | 42 | /* Module Resolution Options */ 43 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 44 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 45 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 46 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 47 | // "typeRoots": [], /* List of folders to include type definitions from. */ 48 | // "types": [], /* Type declaration files to be included in compilation. */ 49 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 50 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 51 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 52 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 53 | 54 | /* Source Map Options */ 55 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 56 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 57 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 58 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 59 | 60 | /* Experimental Options */ 61 | "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 62 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 63 | 64 | /* Advanced Options */ 65 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ 66 | } 67 | // "exclude": [ 68 | // "./module.ts" 69 | // ] 70 | // "include": [ 71 | // "./src/**/*" 72 | // ] 73 | // "files": [ 74 | // "./module.ts" 75 | // ] 76 | } 77 | --------------------------------------------------------------------------------