tools / commit
added typescript cheatsheet
.gitignore | 1 + .vscode/settings.json | 6 +- cheatsheets/apps/index.ts | 169 +++++++++++++++++++++++ cheatsheets/apps/node_modules/.package-lock.json | 19 +++ cheatsheets/apps/package-lock.json | 24 ++++ cheatsheets/apps/package.json | 5 + cheatsheets/apps/tsconfig.json | 44 ++++++ cheatsheets/typescript.md | 151 ++++++++++++++++++++ 8 files changed, 418 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1b97660 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +cheatsheets/apps/node_modules/ diff --git a/.vscode/settings.json b/.vscode/settings.json index e332fc1..852de8c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "cSpell.words": [ + "cheatsheet", "Pavel", "pwsh", "Roadmap", @@ -9,5 +10,8 @@ "Tampermonkey", "Userscripts", "webcomics" - ] + ], + "markdownlint.config": { + "MD031": false + } } \ No newline at end of file diff --git a/cheatsheets/apps/index.ts b/cheatsheets/apps/index.ts new file mode 100644 index 0000000..1116078 --- /dev/null +++ b/cheatsheets/apps/index.ts @@ -0,0 +1,169 @@ +const a = 1; +const b = 2; +const c = a + b; +console.log({ a, b, c }); + +const getUserInput1 = (): string | undefined => { + return "User Input"; +}; +const getUserInput2 = (): number | number[] => { + return [1, 2, 3]; +}; + +const input1 = getUserInput1(); +console.log(`1, type of input1: ${typeof input1}`); +if (typeof input1 === "string") { + console.log("2, input1 is a string:", input1); +} + +const input2 = getUserInput2(); +console.log(`3, type of input2: ${typeof input2}`); +if (input2 instanceof Array) { + console.log("4, input2 is an array:", input2); +} + +console.log(`5, done with type checks`); + +const typeString: string = "This is a string"; +const typeNumber: number = 42; +const typeBoolean: boolean = true; +const typeUndefined: undefined = undefined; +const typeNull: null = null; +const typeVoid: void = undefined; // void is often used for functions that do not return a value +const typeUnknown: unknown = "This could be anything"; + +console.log(`6, done with type checks`); + +const stringArray: string[] = ["apple", "banana", "cherry"]; +const numberArray: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; +if (Array.isArray(stringArray)) { + console.log("7, typeStringArray is an array:", stringArray); +} +if (Array.isArray(numberArray)) { + console.log("8, typeNumberArray is an array:", numberArray); +} + +let subNumArray: number[] = numberArray.slice(1, 6); // Get a sub-array from index 1 to 5 (not including index 6) +console.log(`8.1, subNumArray:`, subNumArray); +subNumArray.push(11); // Add 11 to the end of the array +subNumArray = subNumArray.filter(num => num % 2 === 0); // Filter even numbers +subNumArray.splice(2, 1, 12); // Replace the third element with 12 +subNumArray.shift(); // Remove the first element +subNumArray = subNumArray.concat([13, 14]); // Concatenate with another array +const arraySum = subNumArray.reduce((sum, curr) => sum + curr, 0); // Sum of elements +console.log(`8.2, arraySum:`, arraySum); +console.log(`8.3, subNumArray after changes:`, subNumArray); + +const namedFields: { id: number } = { id: 1 }; +if ("id" in namedFields) { + console.log("9, typeNamedFields has an id field:", namedFields.id); +} + +const object: { id: number; name: string } = { id: 1, name: "Object Name" }; +console.log(`10, typeObject:`, object); +console.log(`11, typeof typeObject:`, typeof object); + +const fn = (param: string): number => { return param.length; }; +console.log(`12, typeFunction:`, fn); +console.log(`13, typeof typeFunction:`, typeof fn); +console.log(`14, typeFunction result:`, fn("Hello")); + +const tuple: [number, string] = [1, "Tuple"]; +console.log(`15, typeTuple:`, tuple); +console.log(`16, typeof typeTuple:`, typeof tuple); + +const now = new Date(); +console.log(`17, Current Date:`, now); +console.log(`18, typeof now:`, typeof now); + +const yesterdayGD = new Date(now); +yesterdayGD.setDate(now.getDate() - 1); +console.log(`19, Yesterday's Date (using getDate()):`, yesterdayGD); + +const yesterdayGT = new Date(now.getTime() - 24 * 60 * 60 * 1000); +console.log(`20, Yesterday's Date (using getTime()):`, yesterdayGT); + +const durationMs = now.getTime() - yesterdayGD.getTime(); +console.log(`21, Duration in milliseconds:`, durationMs); + +const map: Map<string, number> = new Map([ + ["a", 1], + ["b", 2], + ["c", 3] +]); +console.log(`22, map:`, map); + +map.set("d", 4); +map.set("b", 5); +map.delete("c"); +map.get("a"); +console.log(`23, map after modifications:`, map); +map.clear(); + +const set: Set<number> = new Set([1, 2, 3]); +console.log(`24, set:`, set); +set.add(4); +set.add(2); // Duplicate, will not be added +set.delete(1); +set.has(3); +set.size; +console.log(`25, set after modifications:`, set); + +const regex = /p=(\d+),(\d+) v=(-?\d+),(-?\d+)/; +const match = regex.exec("p=1,2 v=-3,4")!; +const pos = { + x: parseInt(match[1]!, 10), + y: parseInt(match[2]!, 10) +}; +const vel = { + x: parseInt(match[3]!, 10), + y: parseInt(match[4]!, 10) +}; + +interface Info { + id: number; + name: string; + coords: { + x: number; + y: number; + }; + expiration?: Date; + tags: string[] | null; + + getInfo: () => string; + findTag(tag: string): boolean; + + get size(): number; + set size(value: number | string); +} +const info: Info = { + id: 1, + name: "Info Object", + coords: { x: 10, y: 20 }, + expiration: new Date(), + tags: ["tag1", "tag2"], + + getInfo() { + return `ID: ${this.id}, Name: ${this.name}, Coords: (${this.coords.x}, ${this.coords.y})`; + }, + + findTag(tag: string): boolean { + return this.tags ? this.tags.includes(tag) : false; + }, + + get size(): number { + return this.tags ? this.tags.length : 0; + }, + set size(value: number | string) { + if (typeof value === "number") { + this.tags = Array(value).fill("defaultTag"); + } else if (typeof value === "string") { + this.tags = [value]; + } + } +}; +info.size = 3; // Set size to 3, will fill with default tags +console.log(`26, info:`, info); +console.log(`27, info.getInfo():`, info.getInfo()); +console.log(`28, info.get size:`, info.size); + diff --git a/cheatsheets/apps/node_modules/.package-lock.json b/cheatsheets/apps/node_modules/.package-lock.json new file mode 100644 index 0000000..17e8325 --- /dev/null +++ b/cheatsheets/apps/node_modules/.package-lock.json @@ -0,0 +1,19 @@ +{ + "name": "apps", + "lockfileVersion": 3, + "requires": true, + "packages": { + "node_modules/typescript": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + } + } +} diff --git a/cheatsheets/apps/package-lock.json b/cheatsheets/apps/package-lock.json new file mode 100644 index 0000000..f1ecc50 --- /dev/null +++ b/cheatsheets/apps/package-lock.json @@ -0,0 +1,24 @@ +{ + "name": "apps", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "typescript": "^5.9.2" + } + }, + "node_modules/typescript": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + } + } +} diff --git a/cheatsheets/apps/package.json b/cheatsheets/apps/package.json new file mode 100644 index 0000000..e70c06e --- /dev/null +++ b/cheatsheets/apps/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "typescript": "^5.9.2" + } +} diff --git a/cheatsheets/apps/tsconfig.json b/cheatsheets/apps/tsconfig.json new file mode 100644 index 0000000..cec4a3a --- /dev/null +++ b/cheatsheets/apps/tsconfig.json @@ -0,0 +1,44 @@ +{ + // Visit https://aka.ms/tsconfig to read more about this file + "compilerOptions": { + // File Layout + // "rootDir": "./src", + // "outDir": "./dist", + + // Environment Settings + // See also https://aka.ms/tsconfig/module + "module": "nodenext", + "target": "esnext", + "types": [], + // For nodejs: + // "lib": ["esnext"], + // "types": ["node"], + // and npm install -D @types/node + + // Other Outputs + "sourceMap": true, + "declaration": true, + "declarationMap": true, + + // Stricter Typechecking Options + "noUncheckedIndexedAccess": true, + "exactOptionalPropertyTypes": true, + + // Style Options + // "noImplicitReturns": true, + // "noImplicitOverride": true, + // "noUnusedLocals": true, + // "noUnusedParameters": true, + // "noFallthroughCasesInSwitch": true, + // "noPropertyAccessFromIndexSignature": true, + + // Recommended Options + "strict": true, + "jsx": "react-jsx", + "verbatimModuleSyntax": true, + "isolatedModules": true, + "noUncheckedSideEffectImports": true, + "moduleDetection": "force", + "skipLibCheck": true, + } +} diff --git a/cheatsheets/typescript.md b/cheatsheets/typescript.md new file mode 100644 index 0000000..130a98e --- /dev/null +++ b/cheatsheets/typescript.md @@ -0,0 +1,151 @@ +# Typescript cheatsheet + +## Starting + +- install + - `npm install TypeScript` +- initialize, creates `tsconfig.json` + - `npx tsc --init` +- build + - `npx tsc` +- run + - `npx ts-node index.ts` + +## Basics + +- variable declaration + - `let`, `const` + - NOT `var` +- variable testing + - `typeof foo` -> `string`, `number`, `bigint`, `boolean`, `symbol`, `undefined`, `object`, `function` + - `instance of Foo` -> `true` if `foo` is an instance of `Foo` +- null-ish stuff + - `??` -> foo ?? 'default' -> returns `foo` it's set, otherwise returns `'default'` + - `!` -> `getFoo()!` -> asserts that `getFoo()` will not return `null` or `undefined` +- basic types + - basics: `string`, `number`, `boolean`, `undefined`, `null`, `void`, `any`, `unknown`, `never` (skipped) + ```ts + const typeString: string = "This is a string"; + const typeNumber: number = 42; + const typeBoolean: boolean = true; + const typeUndefined: undefined = undefined; + const typeNull: null = null; + const typeVoid: void = undefined; // void is often used for functions that do not return a value + const typeUnknown: unknown = "This could be anything"; + ``` + - arrays: `string[]`, `number[]`, `boolean[]` + ```ts + const stringArray: string[] = ["apple", "banana", "cherry"]; + const numberArray: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + const booleanArray: boolean[] = [true, false, true]; + + let sub: number[] = numberArray.slice(1, 6); // Get a sub-array from index 1 to 5 (not including index 6) + sub.push(11); // Add 11 to the end of the array + sub = sub.filter(num => num % 2 === 0); // Filter even numbers + sub.splice(2, 1, 12); // Replace the third element with 12 + sub.shift(); // Remove the first element + sub = sub.concat([13, 14]); // Concatenate with another array + const arraySum = sub.reduce((sum, curr) => sum + curr, 0); // Sum of elements + ``` + - object + - `{ id: number; name: string }` + - function + - `const len = (param: string): number => { return param.length; }` + - `const len = (param: string) => param.length;` + - tuple + - `[string, number]` + ```ts + const tuple: [string, number] = ["apple", 5]; + const [fruit, count] = tuple; + ``` + - Date + ```ts + const now = new Date(); + const yesterdayGD = new Date(now); + yesterdayGD.setDate(now.getDate() - 1); + const yesterdayGT = new Date(now.getTime() - 24 * 60 * 60 * 1000); + const durationMs = now.getTime() - yesterdayGD.getTime(); + ``` + - Map + ```ts + const map: Map<string, number> = new Map([ + ["a", 1], + ["b", 2], + ["c", 3] + ]); + map.get("a"); // returns 1 + map.set("d", 4); + map.has("b"); // returns true + map.delete("c"); // removes key "c" + map.clear(); // removes all entries + ``` + - Note: *DO NOT use `Object` as a map key* + - Set + ```ts + const set: Set<number> = new Set([1, 2, 3]); + set.add(4); + set.add(2); // Duplicate, will not be added + set.delete(1); + ``` + - Regexp + ```ts + const regex = /p=(\d+),(\d+) v=(-?\d+),(-?\d+)/; + const match = regex.exec("p=1,2 v=-3,4")!; + const pos = { + x: parseInt(match[1]!, 10), + y: parseInt(match[2]!, 10) + }; + const vel = { + x: parseInt(match[3]!, 10), + y: parseInt(match[4]!, 10) + }; + ``` +- interfaces + - example, interface + ```ts + interface Info { + id: number; + name: string; + coords: { + x: number; + y: number; + }; + expiration?: Date; + tags: string[] | null; + + getInfo: () => string; + findTag(tag: string): boolean; + + get size(): number; + set size(value: number | string); + } + ``` + - example, initialization + ```ts + const info: Info = { + id: 1, + name: "Info Object", + coords: { x: 10, y: 20 }, + expiration: new Date(), + tags: ["tag1", "tag2"], + + getInfo() { + return `ID: ${this.id}, Name: ${this.name}, Coords: (${this.coords.x}, ${this.coords.y})`; + }, + + findTag(tag: string): boolean { + return this.tags ? this.tags.includes(tag) : false; + }, + + get size(): number { + return this.tags ? this.tags.length : 0; + }, + set size(value: number | string) { + if (typeof value === "number") { + this.tags = Array(value).fill("defaultTag"); + } else if (typeof value === "string") { + this.tags = [value]; + } + } + }; + ```