{"id":19590527,"url":"https://github.com/mudssrali/typescript-cheatsheet","last_synced_at":"2026-04-10T00:02:43.192Z","repository":{"id":53610416,"uuid":"251008081","full_name":"mudssrali/typescript-cheatsheet","owner":"mudssrali","description":"An easy Typescript learning cheat-sheet ","archived":false,"fork":false,"pushed_at":"2024-03-25T03:54:17.000Z","size":335,"stargazers_count":73,"open_issues_count":0,"forks_count":7,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-01-09T06:33:45.166Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mudssrali.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-03-29T10:41:56.000Z","updated_at":"2024-02-21T05:43:23.000Z","dependencies_parsed_at":"2024-11-11T08:28:10.360Z","dependency_job_id":"6058f04c-92e4-434a-bdf5-2a1556ff3508","html_url":"https://github.com/mudssrali/typescript-cheatsheet","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mudssrali%2Ftypescript-cheatsheet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mudssrali%2Ftypescript-cheatsheet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mudssrali%2Ftypescript-cheatsheet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mudssrali%2Ftypescript-cheatsheet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mudssrali","download_url":"https://codeload.github.com/mudssrali/typescript-cheatsheet/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240864570,"owners_count":19869969,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-11T08:25:10.090Z","updated_at":"2026-04-10T00:02:41.146Z","avatar_url":"https://github.com/mudssrali.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\u003cimg src=\"./typescript.png\" width=\"64\" height=\"64\" alt=\"header-image\"\u003e\u003c/p\u003e\n\u003ch2 align=\"center\"\u003eEasy cheatsheet to learn Modern Typescript\u003c/h2\u003e\n\n\u003cp align=\"center\"\n  \u003ca href=\"https://github.com/mudassar045/typescript-cheatsheet\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square\" alt=\"PRs Welcome\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n# Typing Objects\n\n## `Object` vs `object`\n\n-   **Object** is the type of all instances of class **Object** _OR_ Contains stuff (like `toString()`, `hasOwnProperty()`) that is present in all JavaScript objects. Any value (primitive, non-primitive) can be assigned to `Object` type.\n\n    -   It describes functionality that is common to all JavaScript objects\n    -   It includes primitive values\n\n    ```ts\n    const obj = {};\n    obj instanceof Object; // true\n    obj.toString === Object.prototype.toString; // true\n\n    declare function create(x: Object);\n\n    create(\"string\"); // OK\n\n    create(null); // Error\n    create(undefined); // Error\n    ```\n\n-   **object** is the type of all non-primitive values. You can't assign to it any primitive type like `boolean`, `number`, `string`, `bigint`, `symbol`, `null` or `undefined`\n\n    ```ts\n    declare function create(x: object);\n\n    create([]); // OK\n    create({ id: 0 }); // OK\n\n    create(42); // Error\n    create(\"string\"); // Error\n    create(false); // Error\n    create(undefined); // Error\n    ```\n\n-   **{}** is an empty object. It is the same as `Object`\n\n## Interface Signatures Overview\n\n```ts\ninterface RepoInterface {\n    isPublic: boolean; // property signature\n\n    hasRequests(x: string): void; // method signature, 'x' for documentation only\n    hasRequests: (x: string) =\u003e void; // method signature for ES6\n\n    [propName: string]: any; // index signature\n    (x: number): string; // call signature\n    new (x: string): RepoInstance; // construct signature\n\n    readonly admin: string; // readonly modifier\n    readonly [index: number]: string; // you can make index readonly like this\n\n    isArchive?: string; // optional modifier, auto set to undefined\n    isArchive: undefined; // in this case need set the  property\n}\n```\n\n### Index Signature\n\nHelps to describe Arrays or objects that are used as dictionaries.\n\nIf there are both an index signature and property and/or method signatures in an interface, the type of the index property value must also be a `supertype` of the type of the property value and/or method\n\n```ts\ninterface RepoInterface {\n    [propName: string]: boolean;\n\n    // 'number' is not assignable to string index type 'boolean'\n    star: number;\n\n    // '() =\u003e string' is not assignable to string index type 'boolean'\n    isCreated(): string;\n}\n\n// You can resolve above problem like this\n\ninterface RepoInterface {\n    [propName: string]: number;\n    star: number; // OK\n    isCreated(): number; // OK\n}\n\n// Or you can do this to your interface\n\ninterface RepoInterface {\n    [propName: string]: boolean | number | string;\n    star: number; // OK\n    isCreated(): string; // OK\n}\n```\n\n### Call Signature\n\nEnables interfaces to describe functions. **NOTE** `this` is the optional calling context of the function in this example:\n\n```ts\ninterface ClickListener {\n    (this: Window, e: MouseEvent): void;\n}\n\nconst myListener: ClickListener = (e) =\u003e {\n    console.log(\"mouse clicked!\", e);\n};\n\naddEventListener(\"click\", myListener);\n```\n\n### Construct Signature\n\nEnables describing classes and constructor functions. A class has two types:\n\n-   The type of the static side\n-   The type of the instance side\n\nThe constructor sits in the static side, when a class implements an interface,\nonly the instance side of the class is checked.\n\n```ts\ninterface ClockInterface {\n  tick(): void\n}\n\ninterface ClockConstructor {\n  new (h: number, m: number): ClockInterface\n}\n\n/*\n* Using Class Expression\n*/\n\nconst ClockA: ClockConstructor = class Clock implements ClockInterface {\n  constructor(h: number, m: number) {...}\n  tick() {...}\n}\n\nconst clockClassExp = new ClockA(18, 11)\n\n/*\n* Using Class Declaration with a Constructor Function\n*/\n\nclass ClockB implements ClockInterface {\n  constructor(h: number, m: number) {...}\n  tick() {...}\n}\n\nfunction createClock( ctor: ClockConstructor, h: number, m: number): ClockInterface {\n  return new ctor(h, m)\n}\n\nconst clockClassDeclaration = createClock(ClockB, 12, 17)\n```\n\n**[Typescript Docs - Class Type](https://www.typescriptlang.org/docs/handbook/interfaces.html#class-types)**\n\n## Type Literal Syntax\n\nTypically used in the signature of a higher-order function, but it's not limited to this.\n\n```ts\ntype Point = {\n    x: number;\n    y: number;\n};\n\ntype SetPoint = (x: number, y: number) =\u003e void;\n```\n\n## Excess Properties\n\n-   Engineers **can’t** just think of interfaces as “objects that have exactly a\n    set of properties” or “objects that have at least a set of properties”.\n    In-line object arguments receive an additional level of validation that\n    doesn’t apply when they’re passed as variables.\n\n-   TypeScript is a **structurally** typed language. To create a `Dog` you don’t\n    need to explicitly extend the `Dog` interface, any object with a `breed`\n    property that is of type `string` can be used as a `Dog`:\n\n\u003c!-- end list --\u003e\n\n```ts\ninterface Dog {\n    breed: string;\n}\n\nfunction printDog(dog: Dog) {\n    console.log(\"Dog: \" + dog.breed);\n}\n\nconst ginger = {\n    breed: \"Airedale\",\n    age: 3,\n};\n\nprintDog(ginger); // excess properties are OK!\n\nprintDog({ breed: \"Airedale\", age: 3 }); // ERRORS\n\n/*\n  Argument of type '{ breed: string; age: number }' is not assignable to parameter of type 'Dog'.\n  Object literal may only specify known properties, and 'age' does not exist in type 'Dog'.\n*/\n\n// To get rid of above problem, you can define interface with extra proprty with string index signature\n\ninterface Dog {\n    breed: string;\n    [propName: string]: any;\n}\n```\n\n## Interface vs Type\n\nUnlike an **interface** declaration, which always introduces a named `object` type, a **type** alias declaration can introduce a name for any kind of type, including `primitive`, `union`, and `intersection` types. With examples, you can find some in-depth difference between `interface` and `type`.\n\n-   `Objects / Functions`\n\n    Both can be used to describe the shape of an object or a function signature. But the syntax differs.\n\n    **Interface**\n\n    ```ts\n    interface Point {\n        x: number;\n        y: number;\n    }\n\n    interface SetPoint {\n        (x: number, y: number): void;\n    }\n    ```\n\n    **Type alias**\n\n    ```ts\n    type Point = {\n        x: number;\n        y: number;\n    };\n\n    type SetPoint = (x: number, y: number) =\u003e void;\n    ```\n\n-   `Other Types`\n\n    Unlike an interface, the type alias can also be used for other types such as `primitives`, `unions`, and `tuples` (Aforementioned).\n\n    ```ts\n    // primitive\n    type Name = string;\n\n    // object\n    type PartialPointX = { x: number };\n    type PartialPointY = { y: number };\n\n    // union\n    type PartialPoint = PartialPointX | PartialPointY;\n\n    // tuple\n    type Data = [number, string];\n    ```\n\n-   Extend\n\n    Both can be extended, but again, the syntax differs. Additionally, note that an interface and type alias are not mutually exclusive. An interface can extend a type alias, and vice versa.\n\n    **interface extends interface**\n\n    ```ts\n    interface PartialPointX {\n        x: number;\n    }\n    interface Point extends PartialPointX {\n        y: number;\n    }\n    ```\n\n    **type alias extends type alias**\n\n    ```ts\n    type PartialPointX = { x: number };\n    type Point = PartialPointX \u0026 { y: number };\n    ```\n\n    **interface extends type alias**\n\n    ```ts\n    type PartialPointX = { x: number };\n    interface Point extends PartialPointX {\n        y: number;\n    }\n    ```\n\n    **type alias extends interface**\n\n    ```ts\n    interface PartialPointX {\n        x: number;\n    }\n    type Point = PartialPointX \u0026 { y: number };\n    ```\n\n-   `Implements`\n\n    A class can implement an interface or type alias, both in the same exact way. Note however that a class and interface are considered static blueprints. Therefore, they can not `implement / extend` a type alias that names a **union type**.\n\n    ```ts\n    interface Point {\n        x: number;\n        y: number;\n    }\n\n    class SomePoint implements Point {\n        x = 1;\n        y = 2;\n    }\n\n    type Point2 = {\n        x: number;\n        y: number;\n    };\n\n    class SomePoint2 implements Point2 {\n        x = 1;\n        y = 2;\n    }\n\n    type PartialPoint = { x: number } | { y: number };\n\n    // ERROR: can not implement a union type\n    class SomePartialPoint implements PartialPoint {\n        x = 1;\n        y = 2;\n    }\n    /*\n    A class can only implement an object type or intersection of object types with statically known members.\n    */\n    ```\n\n-   `Declaration merging`\n\n    Unlike a type alias, an interface can be defined multiple times, and will be treated as a single interface (with members of all declarations being merged).\n\n    ```ts\n    // These two declarations become:\n    // interface Point { x: number y: number }\n    interface Point {\n        x: number;\n    }\n    interface Point {\n        y: number;\n    }\n\n    const point: Point = { x: 1, y: 2 };\n    ```\n\n# Mapped Types - Getting Types from Data\n\n## `typeof` / `keyof` Examples\n\n```ts\nconst data = {\n    value: 123,\n    text: \"text\",\n    subData: {\n        value: false,\n    },\n};\n\ntype Data = typeof data; // Data = { value: number; text: string; subData: { value: boolean; } }\n```\n\n```ts\nconst data = [\"A\", \"B\"] as const;\ntype Data = typeof data[number]; // \"A\" | \"B\"\n```\n\n```ts\nconst locales = [\n    {\n        locale: \"se\",\n        language: \"Swedish\",\n    },\n    {\n        locale: \"en\",\n        language: \"English\",\n    },\n] as const;\n\ntype Locale = typeof locales[number][\"locale\"]; // \"se\" | \"en\"\n```\n\n```ts\nconst currencySymbols = {\n    GBP: \"£\",\n    USD: \"$\",\n    EUR: \"€\",\n};\ntype CurrencySymbol = keyof typeof currencySymbols; // \"GBP\" | \"USD\" | \"EUR\"\n```\n\n## `keyof` with Generics and Interfaces Example\n\n**Exampl-1**:\n\n```ts\ninterface HasPhoneNumber {\n    name: string;\n    phone: number;\n}\n\ninterface HasEmail {\n    name: string;\n    email: string;\n}\n\ninterface CommunicationMethods {\n    email: HasEmail;\n    phone: HasPhoneNumber;\n    fax: { fax: number };\n}\n\nfunction contact\u003cK extends keyof CommunicationMethods\u003e(\n    method: K,\n    contact: CommunicationMethods[K] // turning key into value - a mapped type\n) {\n    // do something...\n}\n\ncontact(\"email\", { name: \"foo\", email: \"mike@example.com\" });\ncontact(\"phone\", { name: \"foo\", phone: 3213332222 });\ncontact(\"fax\", { fax: 1231 });\n\n// // we can get all values by mapping through all keys\ntype AllCommKeys = keyof CommunicationMethods;\ntype AllCommValues = CommunicationMethods[keyof CommunicationMethods];\n```\n\n**Exampl-2**:\n\nLet's take a `prop` function\n\n```ts\nfunction prop\u003cT, K extends keyof T\u003e(obj: T, key: K) {\n    return obj[key];\n}\n\nconst todo = {\n    id: 1,\n    text: \"Buy milk\",\n    due: new Date(2016, 11, 31),\n};\n\nconst id = prop(todo, \"id\"); // number\nconst text = prop(todo, \"text\"); // string\nconst due = prop(todo, \"due\"); // Date\n```\n\n## Lookup Types\n\n```ts\ninterface Person {\n    name: string;\n    age: number;\n    location: string;\n}\n\ntype P1 = Person[\"name\"]; // string\ntype P2 = Person[\"name\" | \"age\"]; // string | number\n\n// typing from string operations\n\ntype P3 = string[\"charAt\"]; // (pos: number) =\u003e string\ntype P4 = string[][\"push\"]; // (...items: string[]) =\u003e number\ntype P5 = string[][0]; // string\n```\n\nArticle Links:\n\n-   [Keyof and Lookup by Marius Schulz](https://mariusschulz.com/blog/keyof-and-lookup-types-in-typescript)\n-   [More Read about Mapped Types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html#mapped-types)\n\n-   [More Read about Keyof and Lookup Types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html#keyof-and-lookup-types)\n\n# Immutability\n\n## `readonly` Properties\n\nProperties marked with `readonly` can only be assigned to during initialization\nor from within a constructor of the same class.\n\n```ts\ntype Point = {\n    readonly x: number;\n    readonly y: number;\n};\n\nconst origin: Point = { x: 0, y: 0 }; // OK\norigin.x = 100; // Error\n\nfunction moveX(p: Point, offset: number): Point {\n    p.x += offset; // Error\n    return p;\n}\n\nfunction moveX(p: Point, offset: number): Point {\n    // OK\n    return {\n        x: p.x + offset,\n        y: p.y,\n    };\n}\n```\n\n## `readonly` Class Properties\n\nGettable area property is implicitly read-only because there’s no setter:\n\n```ts\nclass Circle {\n    readonly radius: number;\n\n    constructor(radius: number) {\n        this.radius = radius;\n    }\n\n    get area() {\n        return Math.PI * this.radius ** 2;\n    }\n}\n```\n\n## `readonly` Array / Tuple\n\nHere are different usecases of readonly\n\n-   readonly property\n\n    ```ts\n    interface Apple {\n      readonly types: string[]\n      readonly origin: [string, string]\n    }\n\n    const apple: Apple = {\n      types: [\"Asian\", \"American\", \"European\"]\n      origin: [\"Local\", \"Home Grown\"]\n    }\n\n    apple.types.push(\"Russian\") // OK, array is now mutable\n    ```\n\n-   property has readonly type\n\n    ```ts\n    interface Apple {\n      types: readonly string[]\n      origin: readonly [string, string]\n    }\n\n    const apple: Apple = {\n      types: [\"Asian\", \"American\", \"European\"]\n      origin: [\"Local\", \"Home Grown\"]\n    }\n\n    apple.types.push(\"Russian\") // Error, Property `push` does not exist on type 'readonly string[]'\n    ```\n\n-   Variable declaration with readonly\n\n    ```ts\n    const array: readonly string[];\n    const tuple: readonly [string, string];\n    ```\n\n## `const` Assertions\n\n-   `number` becomes number literal\n\n    ```ts\n    // Type '10'\n    let num = 10 as const;\n    ```\n\n-   array literals become `readonly` tuples\n\n    ```ts\n    // Type 'readonly [10, 20]'\n    let tuple = [10, 20] as const;\n    ```\n\n-   object literals get `readonly` properties\n-   no literal types in that expression should be widened (e.g. no going from `\"hello\"` to `string`)\n\n    ```ts\n    // Type '{ readonly text: \"hello\" }'\n    let input = { text: \"hello\" } as const;\n    ```\n\n-   object literals with array types becomes also readonly\n\n    ```ts\n    // Type `{ readonly types: readonly [\"A\", \"B\"]}`\n    let apple = { types: [\"A\", \"B\"] } as const;\n\n    apple.types = [\"C\"]; // Error, 'types' is readonly, we can't reassign\n    apple.push(\"C\"); // Error, Property 'push' does not exist on type 'readonly [\"A\", \"B\", \"C\"]'\n    ```\n\n-   ⛔ `const` contexts **don’t** immediately convert an expression to be fully `immutable`.\n\n    ```ts\n    let types = [\"Asian\", \"European\"];\n\n    let apple = {\n        name: \"Green Apple\",\n        types: types,\n    } as const;\n\n    apple.name = \"Red Apple\"; // Error\n    apple.types = [\"American\"]; // Error\n\n    aaple.types.push(\"African\"); // OK\n\n    // to fix above, just do this little trick\n\n    let types = [\"Asian\", \"European\"] as const;\n    // OR\n    let types: readonly string[] = [\"Asian\", \"European\"];\n    ```\n\n# Strict Mode\n\n```json\n  strict: true /* Enable all strict type-checking options. */\n```\n\nis equivalent to enabling all of the strict mode family options:\n\n```json\n  noImplicitAny: true /* Raise error on expressions and declarations with an implied 'any' type */,\n  strictNullChecks: true /* Enable strict null checks */,\n  strictFunctionTypes: true /* Enable strict checking of function types */,\n  strictBindCallApply: true /* Enable strict 'bind', 'call', and 'apply' methods on functions */,\n  strictPropertyInitialization: true /* Enable strict checking of property initialization in classes */,\n  noImplicitThis: true /* Raise error on 'this' expressions with an implied 'any' type */,\n  alwaysStrict: true /* Parse in strict mode and emit \"use strict\" for each source file */\n```\n\nYou can then turn off individual strict mode family checks as needed.\n\n## Non-Nullable Types `--strictNullChecks`\n\nIn strict null checking mode, `null` and `undefined` are no longer assignable to\nevery type.\n\n```ts\nlet name: string;\nname = \"Marius\"; // OK\nname = null; // Error\nname = undefined; // Error\n```\n\n```ts\nlet name: string | null;\nname = \"Marius\"; // OK\nname = null; // OK\nname = undefined; // Error\n```\n\nOptional parameter `?` automatically adds `| undefined`\n\n```ts\ntype User = {\n    firstName: string;\n    lastName?: string; // same as `string | undefined`\n};\n```\n\n-   In JavaScript, every function parameter is optional, when left off their value\n    is `undefined`.\n-   We can get this functionality in TypeScript by adding a `?` to the end of\n    parameters we want to be optional. This is different from adding `| undefined`\n    which requires the parameter to be explicitly passed as `undefined`\n\n```ts\nfunction fn1(x: number | undefined): void {\n  ...\n}\n\nfunction fn2(x?: number): void {\n  ...\n}\n\nfn1() // Error\nfn2() // OK\nfn1(undefined) // OK\nfn2(undefined) // OK\n```\n\nType guard needed to check if Object is possibly `null`:\n\n```ts\nfunction getLength(s: string | null) {\n    // Error: Object is possibly 'null'.\n    return s.length;\n}\n```\n\n```ts\nfunction getLength(s: string | null) {\n    if (s === null) {\n        return 0;\n    }\n    return s.length;\n}\n\n// JS's truthiness semantics support type guards in conditional expressions\nfunction getLength(s: string | null) {\n    return s ? s.length : 0;\n}\n```\n\n```ts\nfunction doSomething(callback?: () =\u003e void) {\n    // Error: Object is possibly 'undefined'.\n    callback();\n}\n```\n\n```ts\nfunction doSomething(callback?: () =\u003e void) {\n    if (typeof callback === \"function\") {\n        callback();\n    }\n}\n```\n\n## Strict Bind Call Apply `--strictBindCallApply`\n\n\u003e The `call()` method calls a function with a given `this` value and arguments\n\u003e provided individually, while `apply()` accepts a single array of arguments.\n\u003e\n\u003e The `bind()` method creates a new function that, when called, has its `this`\n\u003e keyword set to the provided value.\n\nWhen set, TypeScript will check that the built-in methods of functions `call`,\n`bind`, and `apply` are invoked with correct argument for the underlying\nfunction:\n\n```ts\n// With strictBindCallApply on\nfunction fn(x: string) {\n    return parseInt(x);\n}\n\nconst n1 = fn.call(undefined, \"10\"); // OK\nconst n2 = fn.call(undefined, false); // Argument of type 'false' is not assignable to parameter of type 'string'.\n```\n\n## Strict Class Property Initialization `--strictPropertyInitialization`\n\nVerify that each instance property declared in a class either:\n\n-   Has an explicit initializer, or\n-   Is definitely assigned to in the constructor\n\n```ts\n// Error\nclass User {\n    // Type error: Property 'username' has no initializer\n    // and is not definitely assigned in the constructor\n    username: string;\n}\n\n// OK\nclass User {\n    username = \"n/a\";\n}\n\nconst user = new User();\nconst username = user.username.toLowerCase();\n\n// OK\nclass User {\n    constructor(public username: string) {}\n}\n\nconst user = new User(\"adam\");\nconst username = user.username.toLowerCase();\n```\n\n-   Has a type that includes undefined\n\n```ts\nclass User {\n    username: string | undefined;\n}\n\nconst user = new User();\n\n// Whenever we want to use the username property as a string, we first have\n// to make sure that it actually holds a string, not the value undefined\nconst username =\n    typeof user.username === \"string\" ? user.username.toLowerCase() : \"n/a\";\n```\n\n# Types\n\n## `never`\n\n`never` represents the type of values that never occur. It is used in the\nfollowing two places:\n\n-   As the return type of functions that never return\n-   As the type of variables under type guards that are never true\n\n`never` can be used in control flow analysis:\n\n```ts\nfunction controlFlowAnalysisWithNever(value: string | number) {\n    if (typeof value === \"string\") {\n        value; // Type string\n    } else if (typeof value === \"number\") {\n        value; // Type number\n    } else {\n        value; // Type never\n    }\n}\n```\n\n## `unknown`\n\n`unknown` is the type-safe counterpart of the `any` type: we have to do some\nform of checking before performing most operations on values of type `unknown`.\n\n### Reading `JSON` from `localStorage` using `unknown` Example\n\n```ts\ntype Result =\n    | { success: true; value: unknown }\n    | { success: false; error: Error };\n\nfunction tryDeserializeLocalStorageItem(key: string): Result {\n    const item = localStorage.getItem(key);\n\n    if (item === null) {\n        // The item does not exist, thus return an error result\n        return {\n            success: false,\n            error: new Error(`Item with key \"${key}\" does not exist`),\n        };\n    }\n\n    let value: unknown;\n\n    try {\n        value = JSON.parse(item);\n    } catch (error) {\n        // The item is not valid JSON, thus return an error result\n        return {\n            success: false,\n            error,\n        };\n    }\n\n    // Everything's fine, thus return a success result\n    return {\n        success: true,\n        value,\n    };\n}\n```\n\n# Generics\n\nGenerics enable you to create reusable code components that work with a number\nof types instead of a single type.\n\n## With and Without Type Argument Inference\n\n```ts\nfunction identity\u003cT\u003e(arg: T): T {\n    return arg;\n}\n\nlet output = identity\u003cstring\u003e(\"myString\"); // type of output will be 'string'\nlet output = identity(\"myString\"); // type argument inference\n// compiler sets the value of `T` based on the type of the argument we pass in\n```\n\n## Working with Generic Type Variables\n\n```ts\nfunction loggingIdentity\u003cT\u003e(arg: T): T {\n    console.log(arg.length); // Error: T doesn't have .length\n    return arg;\n}\n\n// to specify .length property we should make generic T to T[] or Array\u003cT\u003e\n\nfunction loggingIdentity\u003cT\u003e(arg: Array\u003cT\u003e): Array\u003cT\u003e {\n    console.log(arg.length); // Array has a .length, so no more error\n    return arg;\n}\n```\n\n## Using More Than One Type Argument\n\nNo value arguments are needed in this case:\n\n```ts\nfunction makePair\u003cF, S\u003e() {\n    let pair: { first: F; second: S };\n\n    function getPair() {\n        return pair;\n    }\n\n    function setPair(x: F, y: S) {\n        pair = {\n            first: x,\n            second: y,\n        };\n    }\n    return { getPair, setPair };\n}\n\n// Creates a (number, string) pair\nconst { getPair, setPair } = makePair\u003cnumber, string\u003e();\n\nsetPair(1, \"y\"); // must be type of (number, string)\ngetPair(); // will return pair of type { number, string }\n```\n\n## Higher Order Function with `Parameters\u003cT\u003e` and `ReturnType\u003cT\u003e`\n\n```ts\n// Input a function `\u003cT extends (...args: any[]) =\u003e any\u003e`\n// Output a function with same params and return type `:(...funcArgs: Parameters\u003cT\u003e) =\u003e ReturnType\u003cT\u003e`\n\nfunction logDuration\u003cT extends (...args: any[]) =\u003e any\u003e(func: T) {\n    const funcName = func.name;\n\n    // Return a new function that tracks how long the original took\n    return (...args: Parameters\u003cT\u003e): ReturnType\u003cT\u003e =\u003e {\n        console.time(funcName);\n        const results = func(...args);\n        console.timeEnd(funcName);\n        return results;\n    };\n}\n\nfunction addNumbers(a: number, b: number): number {\n    return a + b;\n}\n// Hover over is `addNumbersWithLogging: (a: number, b: number) =\u003e number`\nconst addNumbersWithLogging = logDuration(addNumbers);\n\naddNumbersWithLogging(5, 3);\n```\n\nA generic class has a similar shape to a generic interface. Generic classes have a generic type parameter list in angle brackets (`\u003c\u003e`) following the name of the class.\n\n```ts\nclass GenericNumber\u003cT\u003e {\n    zeroValue: T;\n    add: (x: T, y: T) =\u003e T;\n}\n\nlet myGenericNumber = new GenericNumber\u003cnumber\u003e();\n\nmyGenericNumber.zeroValue = 0;\nmyGenericNumber.add = function (x, y) {\n    return x + y;\n};\n```\n\n# Discriminated Unions\n\nDiscriminated Unions provide a powerful pattern in TypeScript. Immensely useful for actions \u0026 reducers in `ngrx/redux`, and every time you have to distinguish between `kinds` of objects. They enaWtype inference which, combined with strict null checks, will catch a lot of bugs! [By Minko Gechev](https://twitter.com/mgechev/status/1255021510563115008)\n\n```ts\nconst enum Entity {\n    Individual,\n    Corporation,\n}\n\ninterface Individual {\n    type: Entity.Individual;\n    ssn: string;\n}\n\ninterface Corporation {\n    type: Entity.Corporation;\n    ein: string;\n}\n\ntype TaxPayer = Individual | Corporation;\n\nfunction magic(payer: TaxPayer) {\n    if (payer.type === Entity.Individual) {\n        taxIdentifier(payer.ssn);\n        taxIdentifier(payer.ein); // Property 'ein' does not exist on type 'Individual'\n    } else {\n        taxIdentifier(payer.ein);\n        taxIdentifier(payer.ssn); // Property 'ssn' doesn't exist on type 'Corporation'\n    }\n}\n```\n\n# Optional Chaining\n\n## `?.` returns `undefined` when hitting a `null` or `undefined`\n\nAlbum where the artist, and the artists biography might not be present in the\ndata.\n\n```ts\ntype AlbumAPIResponse = {\n    title: string;\n    artist?: {\n        name: string;\n        bio?: string;\n        previousAlbums?: string[];\n    };\n};\n\n// Instead of:\nconst maybeArtistBio = album.artist \u0026\u0026 album.artist.bio;\n\n// ?. acts differently than \u0026\u0026 on \"falsy\" values: empty string, 0, NaN, false\nconst artistBio = album?.artist?.bio;\n\n// optional chaining also works with the [] operators when accessing elements\n// see more example for optional element access below\nconst maybeArtistBioElement = album?.[\"artist\"]?.[\"bio\"];\nconst maybeFirstPreviousAlbum = album?.artist?.previousAlbums?.[0];\n```\n\nOptional chaining on an optional function:\n\n```ts\ninterface OptionalFunction {\n    bar?: () =\u003e number;\n}\n\nconst foo: OptionalFunction = {};\nconst bat = foo.bar?.(); // number | undefined\n```\n\n-   `Optional Element Access`\n\nthe _optional element access_ which acts similarly to _optional property_ accesses, but allows us to access non-identifier properties (e.g. arbitrary strings, numbers, and symbols):\n\n```ts\n/**\n * Get the first element of the array if we have an array.\n * Otherwise return undefined.\n */\nfunction tryGetFirstElement\u003cT\u003e(arr?: T[]) {\n    return arr?.[0];\n\n    // equivalent to\n    //   return (arr === null || arr === undefined) ?\n    //       undefined :\n    //       arr[0]\n}\n```\n\n-   `Optional Call`\n\n_optional call_, which allows us to conditionally call expressions if they’re not `null` or `undefined`.\n\n```ts\nasync function makeRequest(url: string, log?: (msg: string) =\u003e void) {\n    log?.(`Request started at ${new Date().toISOString()}`);\n\n    // roughly equivalent to\n    //   if (log != null) {\n    //       log(`Request started at ${new Date().toISOString()}`)\n    //   }\n\n    const result = (await fetch(url)).json();\n\n    log?.(`Request finished at at ${new Date().toISOString()}`);\n\n    return result;\n}\n```\n\n-   `Short-circutting`\n\nThe _short-circuiting_ behavior that optional chains have is limited property accesses, calls, element accesses - it doesn’t expand any further out from these expressions.\n\n```ts\nlet result = foo?.bar / someComputation();\n// doesn’t stop the division or someComputation() call from occurring. It’s equivalent to\n\nlet temp = foo === null || foo === undefined ? undefined : foo.bar;\n\nlet result = temp / someComputation();\n```\n\n# Nullish Coalescing\n\n## `??` “fall Backs” to a Default Value When Dealing with `null` or `undefined`\n\nValue `foo` will be used when it’s “present”; but when it’s `null` or\n`undefined`, calculate `bar()` in its place.\n\n```ts\nlet x = foo ?? bar();\n// instead of\nlet x = foo !== null \u0026\u0026 foo !== undefined ? foo : bar();\n```\n\nIt can replace uses of `||` when trying to use a default value, and avoids bugs.\nWhen `localStorage.volume` is set to `0`, the page will set the volume to `0.5`\nwhich is unintended. `??` avoids some unintended behaviour from `0`, `NaN` and\n`\"\"` being treated as falsy values.\n\n```ts\nfunction initializeAudio() {\n    let volume = localStorage.volume || 0.5; // Potential bug\n}\n```\n\n# Comments\n\n## ts-expect-error - 3.9\n\nTypeScript 3.9 brings a new feature: `// @ts-expect-error` comments. When a line is prefixed with a `// @ts-expect-error` comment, TypeScript will suppress that error from being reported; but if there’s no error, TypeScript will report that `// @ts-expect-error` wasn’t necessary.\n\n```ts\n// @ts-expect-error\nconsole.log(47 * \"octopus\"); // OK, no problem here\n\n// @ts-expect-error\nconsole.log(1 + 1); // Unused '@ts-expect-error' directive.\n```\n\n## ts-expect-error vs ts-ignore\n\nIn some ways `// @ts-expect-error` can act as a suppression comment, similar to `// @ts-ignore`. The difference is that `// @ts-ignore` will do nothing if the following line is error-free.\n\nYou might be tempted to switch existing `// @ts-ignore` comments over to `// @ts-expect-error`, and you might be wondering which is appropriate for future code. While it’s entirely up to you and your team, we have some ideas of which to pick in certain situations.\n\n**Pick `ts-expect-error` if**:\n\n-   you’re writing test code where you actually want the type system to error on an operation\n-   you expect a fix to be coming in fairly quickly and you just need a quick workaround\n-   you’re in a reasonably-sized project with a proactive team that wants to remove suppression comments as soon affected code is valid again\n\n**Pick `ts-ignore` if**:\n\n-   you have an a larger project and and new errors have appeared in code with no clear owner\n-   you are in the middle of an upgrade between two different versions of TypeScript, and a line of code errors in one version but not another.\n-   you honestly don’t have the time to decide which of these options is better\n\n## TS 4.0 - 4.2\n\n- [ ] Short-Circuiting Assignment Operators\n- [ ] Template Literal Types\n- [ ] Key Remapping in Mapped Types\n- [ ] Checked Indexed Accesses (--noUncheckedIndexedAccess)\n- [ ] Paths without baseUrl\n- [ ] Destructured Variables Can Be Explicitly Marked as Unused\n\n## TS 4.3 - 4.4\n\n- [ ] (Template String Type Improvements)\n- [ ] (Editor Support for @link Tags)\n- [ ] (Go-to-Definition on Non-JavaScript File Paths)\n- [ ] (Inlay Hints)\n\n## TS 4.5 - 5.4\n\n\u003e Will update soon\n\n\u003c/article\u003e\n\n[:arrow_up: Back to top](#easy-cheatsheet-to-learn-modern-typescript)\n\nThanks goes to these people for great examples:\n\n-   [Typescript Lang Organization](https://www.typescriptlang.org/)\n-   [David-Else](http://github.com/David-Else)\n-   [Marius Schulz](https://github.com/mariusschulz)\n-   [Shu Uesugi](https://github.com/chibicode)\n-   [Axel Rauschmayer](https://github.com/rauschma)\n-   [Minko Gechev](https://github.com/mgechev)\n\n**[MIT-LICENSE](./LICENSE)**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmudssrali%2Ftypescript-cheatsheet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmudssrali%2Ftypescript-cheatsheet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmudssrali%2Ftypescript-cheatsheet/lists"}