diff --git a/Sample/package-lock.json b/Sample/package-lock.json index 6725088..2c5ecd7 100644 --- a/Sample/package-lock.json +++ b/Sample/package-lock.json @@ -10,10 +10,6 @@ "license": "ISC", "dependencies": { "parcel": "^2.9.3" - }, - "devDependencies": { - "@parcel/transformer-typescript-tsc": "^2.9.3", - "typescript": "^5.2.2" } }, "node_modules/@babel/code-frame": { @@ -1423,47 +1419,6 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/transformer-typescript-tsc": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/@parcel/transformer-typescript-tsc/-/transformer-typescript-tsc-2.9.3.tgz", - "integrity": "sha512-kQUts/PVFhEb9JoyJBlKvaa5qR/3bEiyZSjn8qE3S+97CUOIVun8fNxGiDPwpaPd90BgPcgU43gSAQwlY9rIMQ==", - "dev": true, - "dependencies": { - "@parcel/plugin": "2.9.3", - "@parcel/source-map": "^2.1.1", - "@parcel/ts-utils": "2.9.3" - }, - "engines": { - "node": ">= 12.0.0", - "parcel": "^2.9.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "peerDependencies": { - "typescript": ">=3.0.0" - } - }, - "node_modules/@parcel/ts-utils": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/@parcel/ts-utils/-/ts-utils-2.9.3.tgz", - "integrity": "sha512-MiQoXFV8I4IWZT/q5yolKN/gnEY5gZfGB2X7W9WHJbRgyjlT/A5cPERXzVBj6mc3/VM1GdZJz76w637GUcQhow==", - "dev": true, - "dependencies": { - "nullthrows": "^1.1.1" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "peerDependencies": { - "typescript": ">=3.0.0" - } - }, "node_modules/@parcel/types": { "version": "2.9.3", "resolved": "https://registry.npmjs.org/@parcel/types/-/types-2.9.3.tgz", @@ -3286,7 +3241,8 @@ "version": "5.2.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", - "devOptional": true, + "optional": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/Sample/src/index.html b/Sample/src/index.html index cd350ba..e847082 100644 --- a/Sample/src/index.html +++ b/Sample/src/index.html @@ -7,6 +7,11 @@

Typescript training

+
+ + + +
diff --git a/Sample/src/index.ts b/Sample/src/index.ts index d2cdacb..aa4e3c1 100644 --- a/Sample/src/index.ts +++ b/Sample/src/index.ts @@ -126,3 +126,94 @@ // let customer = getCustomer(1); // console.log(customer?.birthday?.getDate); + +// Generics +// function extractAndConvert( +// obj: T, +// key: U +// ) { +// return "Value: " + obj[key]; +// } + +// extractAndConvert({ name: "Max" }, "name"); + +// class DataStorage { +// private data: T[] = []; + +// addItem(item: T) { +// this.data.push(item); +// } + +// removeItem(item: T) { +// if (this.data.indexOf(item) === -1) { +// return; +// } +// this.data.splice(this.data.indexOf(item), 1); // -1 +// } + +// getItems() { +// return [...this.data]; +// } +// } + +// const textStorage = new DataStorage(); +// textStorage.addItem("Max"); +// textStorage.addItem("Manu"); +// textStorage.removeItem("Max"); +// console.log(textStorage.getItems()); + +// Decorators + +const config: { [input: string]: string[] } = {}; + +const addValidator = (input: string, type: string) => { + config[input] = config[input] ? [...config[input], type] : [type]; + + console.log(input, type); +}; + +const Required = (_: any, prop: string) => { + addValidator(prop, "required"); +}; +const Maxlength = (_: any, prop: string) => addValidator(prop, "maxlength"); +const Positive = (_: any, prop: string) => addValidator(prop, "positive"); + +const validate = (course: any) => + Object.entries(config).every(([input, types]) => + types.every( + (type) => + (type === "required" && course[input]) || + (type === "positive" && course[input] > 0) || + (type === "maxlength" && course[input].length < 5) + ) + ); + +class Course { + @Required @Maxlength title: string; + @Required @Positive price: number; + + constructor(title: string, price: number) { + this.title = title; + this.price = price; + } +} + +const courseForm = document.querySelector("form")!; +courseForm.addEventListener("submit", (event) => { + event.preventDefault(); + const titleEl = document.getElementById("title") as HTMLInputElement; + const priceEl = document.getElementById("price") as HTMLInputElement; + + const title = titleEl.value; + const price = +priceEl.value; + + const createdCourse = new Course(title, price); + + if (!validate(createdCourse)) { + alert("Invalid input, please try again!"); + return; + } + console.log(createdCourse); +}); + +console.log(config); diff --git a/Sample/tsconfig.json b/Sample/tsconfig.json index e6210ec..828316c 100644 --- a/Sample/tsconfig.json +++ b/Sample/tsconfig.json @@ -12,9 +12,14 @@ /* Language and Environment */ "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + "lib": [ + "dom", + "ES2017", + "dom.iterable", + "scripthost" + ] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + "experimentalDecorators": true /* Enable experimental support for legacy experimental decorators. */, // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */