fuzzyworld

tools / commit

added typescript cheatsheet

3aee11a43130f559de7cdc53d249a33fc39ea10c · Pavel Safronov · 2025-08-15 08:45:05 -0700 · parents 89528c89ce98

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];
+            }
+        }
+    };
+    ```