{"id":13751518,"url":"https://github.com/jellydn/typescript-tips","last_synced_at":"2025-05-16T02:07:13.642Z","repository":{"id":63368949,"uuid":"567322406","full_name":"jellydn/typescript-tips","owner":"jellydn","description":"A curated list of awesome 🔥 TypeScript Tips 🔥","archived":false,"fork":false,"pushed_at":"2025-05-12T05:12:23.000Z","size":62682,"stargazers_count":429,"open_issues_count":2,"forks_count":90,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-05-12T06:24:54.317Z","etag":null,"topics":["awesome-list","hacktoberfest","tips-and-tricks","typescript"],"latest_commit_sha":null,"homepage":"https://jellydn.github.io/typescript-tips/","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jellydn.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":"docs/contributing.md","funding":null,"license":null,"code_of_conduct":"docs/code-of-conduct.md","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,"zenodo":null},"funding":{"github":["jellydn"],"ko_fi":"dunghd","buy_me_a_coffee":"dunghd","polar":"jellydn"}},"created_at":"2022-11-17T14:46:36.000Z","updated_at":"2025-05-12T05:12:26.000Z","dependencies_parsed_at":"2023-02-19T04:45:59.539Z","dependency_job_id":"e5ba37a3-09c6-4506-badf-53483ec59fda","html_url":"https://github.com/jellydn/typescript-tips","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/jellydn%2Ftypescript-tips","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jellydn%2Ftypescript-tips/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jellydn%2Ftypescript-tips/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jellydn%2Ftypescript-tips/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jellydn","download_url":"https://codeload.github.com/jellydn/typescript-tips/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254453651,"owners_count":22073617,"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":["awesome-list","hacktoberfest","tips-and-tricks","typescript"],"created_at":"2024-08-03T09:00:47.261Z","updated_at":"2025-05-16T02:07:13.621Z","avatar_url":"https://github.com/jellydn.png","language":null,"readme":"# Typescript Tips [![Awesome](https://awesome.re/badge.svg)](https://awesome.re)\n\n\u003e A curated list of awesome 🔥 TypeScript Tips 🔥\n\nIf you enjoy TypeScript and really want to use Typesafe, you can check [awesome-typesafe](https://github.com/jellydn/awesome-typesafe)\n\n## 🏠 [Homepage](https://github.com/jellydn/typescript-tips)\n\n### ✨ [Gitbook](https://productsway.gitbook.io/typescript-tips/)\n\n## Contents\n\n- [Tips](#tips)\n  - [Matt Pocock](#matt-pocock)\n  - [Wes Bos](#wes-bos)\n  - [Erik Rasmussen](#erik-rasmussen)\n  - [Carlos Caballero](#carlos-caballero)\n  - [Ankita Kulkarni](#ankita-kulkarni)\n  - [Minko Gechev](#minko-gechev)\n  - [Cory House](#cory-house)\n  - [Tomek Sułkowski](#tomek-sułkowski)\n  - [Sebastien Lorber](#sebastien-lorber)\n  - [Steve (Builder.io)](#steve-builderio)\n  - [StackBlitz](#stackblitz)\n  - [Extending existing types](#extending-existing-types)\n  - [Built-in types](#built-in-types)\n- [Contribute](#contribute)\n  - [Twitter to markdown file](#twitter-to-markdown-file)\n- [Credits](#credits)\n\n## Tips\n\n### Matt Pocock\n\n- [TypeScript Tips Series](https://www.totaltypescript.com/tips)\n- [LooseAutocomplete](\u003cnotes/mattpocockuk - 1506607945445949446.md\u003e)\n- [Normal union, a discriminated union, and a type predicate](notes/mattpocockuk%20-%201592130978234900484.md)\n- [Enter satisfies()() 👀](notes/mattpocockuk%20-%201536670032360611840.md)\n- [Use Object.freeze to ensure your objects are readonly at the type level AND the runtime level](notes/mattpocockuk%20-%201542079199543975937.md)\n- [Inversion of control](notes/mattpocockuk%20-%201591047557702389760.md)\n- [Ultimate TypeScript Thread](notes/mattpocockuk%20-%201509964736275927042.md)\n- [Expose type to global with declare global](notes/mattpocockuk%20-%201593584053042630657.md)\n- [Use generics to dynamically specify the number, and type, of arguments to functions](notes/mattpocockuk%20-%201509850662795989005.md)\n- [Adding things to the global scope in TypeScript](notes/mattpocockuk%20-%201590333383501979649.md)\n- [Using 'as const' over enums](notes/mattpocockuk%20-%201598708710523772929.md)\n- [Use assertion functions inside classes](notes/mattpocockuk%20-%201512388535692652547.md)\n- [Compound Components in React are SUPER easy to type in TS](notes/mattpocockuk%20-%201638562171863834625.md)\n\n### Wes Bos\n\n- [Four ways to define an object type in TypeScript](notes/wesbos%20-%201524040757518258176.md)\n- [The difference between `any` and `unknown`](notes/wesbos%20-%201584905090628034560.md)\n- [Use TypeScript's `never` for making sure you hit every scenario](notes/wesbos%20-%201585641232155348992.md)\n- [Use TypeScript's `never` to enforce \"one or the other\" properties on a type](notes/wesbos%20-%201587082842110033926.md)\n- [Type Guard in TypeScript by using the `is` keyword in a functions return type](notes/wesbos%20-%201585258976421224450.md)\n- [VSCode - quickly add all properties to a typed object in TypeScript with the ts-quickfixes](notes/wesbos%20-%201582803702225989637.md)\n- [VSCode - refactoring your codebase](notes/wesbos%20-%201583093975359315968.md)\n- [4 TypeScript tips in context of when you would use them. as const, typeof, keyof and template string types](notes/wesbos%20-%201615777112408866832.md)\n\n### Erik Rasmussen\n\n- [Passing around unique identifiers of objects, select the type of the identifier right off of the object type](notes/erikras%20-%201457999235564154882.md)\n\n### Carlos Caballero\n\n- [Use look up tables instead of \"if\"](notes/Carlillo%20-%201591148366070747347.md)\n\n### Ankita Kulkarni\n\n- [Typescript 4.9 satisfies operator - check if the type matches one of these listed type](notes/kulkarniankita9%20-%201594154991148597250.md)\n\n### Minko Gechev\n\n- [Enum vs const enums](notes/mgechev%20-%201309379618034642946.md)\n- [Use labeled tuple elements to get better hints from your text editor ](notes/mgechev%20-%201361186013029269506.md)\n- [Use `as const` after literals](notes/mgechev%20-%201462654597059817481.md)\n\n### Cory House\n\n- [Avoid making a property optional when the property isn’t valid in a certain case](notes/housecor%20-%201581638360543600640.md)\n- [Alias the type's name when conflicts with an existing identifier](notes/housecor%20-%201586865516395876359.md)\n- [Many optional properties are a code smell](notes/housecor%20-%201596861970170671104.md)\n\n### Tomek Sułkowski\n\n- [Extract it from a component using the handy `ComponentProps`](notes/sulco%20-%201160890708615716864.md)\n- [Use `keyof` gets a union type of all properties of the given object](notes/sulco%20-%201222507593287028736.md)\n\n### Sebastien Lorber\n\n- [No need to import DOM event handler types](notes/sebastienlorber%20-%201512420374201446405.md)\n\n### Steve (Builder.io)\n\n- [The `satisfies` operator in TypeScript 4.9 is a game changer](notes/Steve8708%20-%201605322303319199744.md)\n\n### StackBlitz\n\n- [Infers array's type as const](notes/stackblitz%20-%201325818478675304448.md)\n- [How to use extends](notes/stackblitz%20-%201328353096179789824.md)\n- [How to use readonly](notes/stackblitz%20-%201330890655351123968.md)\n\n### Extending existing types\n\n- [`PackageJson`](https://github.com/sindresorhus/type-fest/blob/main/source/package-json.d.ts) - There are a lot of tools that\n  place extra configurations inside the `package.json` file. You can extend\n  `PackageJson` to support these additional configurations.\n  \u003cdetails\u003e\n  \u003csummary\u003e\n  \t\tExample\n  \u003c/summary\u003e\n\n  [Playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBDAnmApnA3gBQIYGMDW2A5igFIDOEAdnNuXAEJ0o4HFmVUC+cAZlBBBwA5ElQBaXinIxhAbgCwAKFCRYCZGnQAZYFRgooPfoJHSANntmKlysWlaESFanAC8jZo-YuaAMgwLKwBhal5gIgB+AC44XX1DADpQqnCiLhsgA)\n\n  ```ts\n  import type { PackageJson as BasePackageJson } from \"type-fest\";\n  import type { Linter } from \"eslint\";\n\n  type PackageJson = BasePackageJson \u0026 { eslintConfig?: Linter.Config };\n  ```\n\n  \u003c/details\u003e\n\n### Built-in types\n\nThere are many advanced types most users don't know about.\n\n- [`Partial\u003cT\u003e`](https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype) -\n  Make all properties in `T` optional.\n  \u003cdetails\u003e\n  \u003csummary\u003e\n  \t\tExample\n  \u003c/summary\u003e\n\n  [Playground](https://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgHIHsAmEDC6QzADmyA3gLABQyycADnanALYQBcyAzmFKEQNxUaddFDAcQAV2YAjaIMoBfKlQQAbOJ05osEAIIMAQpOBrsUMkOR1eANziRkCfISKSoD4Pg4ZseAsTIALyW1DS0DEysHADkvvoMMQA0VsKi4sgAzAAMuVaKClY2wPaOknSYDrguADwA0sgQAB6QIJjaANYQAJ7oMDp+LsQAfAAUXd0cdUnI9mo+uv6uANp1ALoAlKHhyGAAFsCcAHTOAW4eYF4gyxNrwbNwago0ypRWp66jH8QcAApwYmAjxq8SWIy2FDCNDA3ToKFBQyIdR69wmfQG1TOhShyBgomQX3w3GQE2Q6IA8jIAFYQBBgI4TTiEs5bTQYsFInrLTbbHZOIlgZDlSqQABqj0kKBC3yINx6a2xfOQwH6o2FVXFaklwSCIUkbQghBAEEwENSfNOlykEGefNe5uhB2O6sgS3GPRmLogmslG1tLxUOKgEDA7hAuydtteryAA)\n\n  ```ts\n  interface NodeConfig {\n    appName: string;\n    port: number;\n  }\n\n  class NodeAppBuilder {\n    private configuration: NodeConfig = {\n      appName: \"NodeApp\",\n      port: 3000,\n    };\n\n    private updateConfig\u003cKey extends keyof NodeConfig\u003e(\n      key: Key,\n      value: NodeConfig[Key]\n    ) {\n      this.configuration[key] = value;\n    }\n\n    config(config: Partial\u003cNodeConfig\u003e) {\n      type NodeConfigKey = keyof NodeConfig;\n\n      for (const key of Object.keys(config) as NodeConfigKey[]) {\n        const updateValue = config[key];\n\n        if (updateValue === undefined) {\n          continue;\n        }\n\n        this.updateConfig(key, updateValue);\n      }\n\n      return this;\n    }\n  }\n\n  // `Partial\u003cNodeConfig\u003e`` allows us to provide only a part of the\n  // NodeConfig interface.\n  new NodeAppBuilder().config({ appName: \"ToDoApp\" });\n  ```\n\n  \u003c/details\u003e\n\n- [`Required\u003cT\u003e`](https://www.typescriptlang.org/docs/handbook/utility-types.html#requiredtype) -\n  Make all properties in `T` required.\n  \u003cdetails\u003e\n  \u003csummary\u003e\n  \t\tExample\n  \u003c/summary\u003e\n\n  [Playground](https://typescript-play.js.org/?target=6#code/AQ4SwOwFwUwJwGYEMDGNgGED21VQGJZwC2wA3gFCjXAzFJgA2A-AFzADOUckA5gNxUaIYjA4ckvGG07c+g6gF8KQkAgCuEFFDA5O6gEbEwUbLm2ESwABQIixACJIoSdgCUYAR3Vg4MACYAPGYuFvYAfACU5Ko0APRxwADKMBD+wFAAFuh2Vv7OSBlYGdmc8ABu8LHKsRyGxqY4oQT21pTCIHQMjOwA5DAAHgACxAAOjDAAdChYxL0ANLHUouKSMH0AEmAAhJhY6ozpAJ77GTCMjMCiV0ToSAb7UJPPC9WRgrEJwAAqR6MwSRQPFGUFocDgRHYxnEfGAowh-zgUCOwF6KwkUl6tXqJhCeEsxDaS1AXSYfUGI3GUxmc0WSneQA)\n\n  ```ts\n  interface ContactForm {\n    email?: string;\n    message?: string;\n  }\n\n  function submitContactForm(formData: Required\u003cContactForm\u003e) {\n    // Send the form data to the server.\n  }\n\n  submitContactForm({\n    email: \"ex@mple.com\",\n    message: \"Hi! Could you tell me more about�\",\n  });\n\n  // TypeScript error: missing property 'message'\n  submitContactForm({\n    email: \"ex@mple.com\",\n  });\n  ```\n\n  \u003c/details\u003e\n\n- [`Readonly\u003cT\u003e`](https://www.typescriptlang.org/docs/handbook/utility-types.html#readonlytype) -\n  Make all properties in `T` readonly.\n  \u003cdetails\u003e\n  \u003csummary\u003e\n  \t\tExample\n  \u003c/summary\u003e\n\n  [Playground](https://typescript-play.js.org/?target=6#code/AQ4UwOwVwW2AZA9gc3mAbmANsA3gKFCOAHkAzMgGkOJABEwAjKZa2kAUQCcvEu32AMQCGAF2FYBIAL4BufDRABLCKLBcywgMZgEKZOoDCiCGSXI8i4hGEwwALmABnUVxXJ57YFgzZHSVF8sT1BpBSItLGEnJz1kAy5LLy0TM2RHACUwYQATEywATwAeAITjU3MAPnkrCJMXLigtUT4AClxgGztKbyDgaX99I1TzAEokr1BRAAslJwA6FIqLAF48TtswHp9MHDla9hJGACswZvmyLjAwAC8wVpm5xZHkUZDaMKIwqyWXYCW0oN4sNlsA1h0ug5gAByACyBQAggAHJHQ7ZBIFoXbzBjMCz7OoQP5YIaJNYQMAAdziCVaALGNSIAHomcAACoFJFgADKWjcSNEwG4vC4ji0wggEEQguiTnMEGALWAV1yAFp8gVgEjeFyuKICvMrCTgVxnst5jtsGC4ljsPNhXxGaAWcAAOq6YRXYDCRg+RWIcA5JSC+kWdCepQ+v3RYCU3RInzRMCGwlpC19NYBW1Ye08R1AA)\n\n  ```ts\n  enum LogLevel {\n    Off,\n    Debug,\n    Error,\n    Fatal,\n  }\n\n  interface LoggerConfig {\n    name: string;\n    level: LogLevel;\n  }\n\n  class Logger {\n    config: Readonly\u003cLoggerConfig\u003e;\n\n    constructor({ name, level }: LoggerConfig) {\n      this.config = { name, level };\n      Object.freeze(this.config);\n    }\n  }\n\n  const config: LoggerConfig = {\n    name: \"MyApp\",\n    level: LogLevel.Debug,\n  };\n\n  const logger = new Logger(config);\n\n  // TypeScript Error: cannot assign to read-only property.\n  logger.config.level = LogLevel.Error;\n\n  // We are able to edit config variable as we please.\n  config.level = LogLevel.Error;\n  ```\n\n  \u003c/details\u003e\n\n- [`Pick\u003cT, K\u003e`](https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys) -\n  From `T`, pick a set of properties whose keys are in the union `K`.\n  \u003cdetails\u003e\n  \u003csummary\u003e\n  \t\tExample\n  \u003c/summary\u003e\n\n  [Playground](https://typescript-play.js.org/?target=6#code/AQ4SwOwFwUwJwGYEMDGNgEE5TCgNugN4BQoZwOUBAXMAM5RyQDmA3KeSFABYCuAtgCMISMHloMmENh04oA9tBjQJjFuzIBfYrOAB6PcADCcGElh1gEGAHcKATwAO6ebyjB5CTNlwFwSxFR0BX5HeToYABNgBDh5fm8cfBg6AHIKG3ldA2BHOOcfFNpUygJ0pAhokr4hETFUgDpswywkggAFUwA3MFtgAF5gQgowKhhVKTYKGuFRcXo1aVZgbTIoJ3RW3xhOmB6+wfbcAGsAHi3kgBpgEtGy4AAfG54BWfqAPnZm4AAlZUj4MAkMA8GAGB4vEgfMlLLw6CwPBA8PYRmMgZVgAC6CgmI4cIommQELwICh8RBgKZKvALh1ur0bHQABR5PYMui0Wk7em2ADaAF0AJS0AASABUALIAGQAogR+Mp3CROCAFBBwVC2ikBpj5CgBIqGjizLA5TAFdAmalImAuqlBRoVQh5HBgEy1eDWfs7J5cjzGYKhroVfpDEhHM4MV6GRR5NN0JrtnRg6BVirTFBeHAKYmYY6QNpdB73LmCJZBlSAXAubtvczeSmQMNSuMbmKNgBlHFgPEUNwusBIPAAQlS1xetTmxT0SDoESgdD0C4aACtHMwxytLrohawgA)\n\n  ```ts\n  interface Article {\n    title: string;\n    thumbnail: string;\n    content: string;\n  }\n\n  // Creates new type out of the `Article` interface composed\n  // from the Articles' two properties: `title` and `thumbnail`.\n  // `ArticlePreview = {title: string; thumbnail: string}`\n  type ArticlePreview = Pick\u003cArticle, \"title\" | \"thumbnail\"\u003e;\n\n  // Render a list of articles using only title and description.\n  function renderArticlePreviews(previews: ArticlePreview[]): HTMLElement {\n    const articles = document.createElement(\"div\");\n\n    for (const preview of previews) {\n      // Append preview to the articles.\n    }\n\n    return articles;\n  }\n\n  const articles = renderArticlePreviews([\n    {\n      title: \"TypeScript tutorial!\",\n      thumbnail: \"/assets/ts.jpg\",\n    },\n  ]);\n  ```\n\n  \u003c/details\u003e\n\n- [`Record\u003cK, T\u003e`](https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type) -\n  Construct a type with a set of properties `K` of type `T`.\n  \u003cdetails\u003e\n  \u003csummary\u003e\n  \t\tExample\n  \u003c/summary\u003e\n\n  [Playground](https://typescript-play.js.org/?target=6#code/AQ4ejYAUHsGcCWAXBMB2dgwGbAKYC2ADgDYwCeeemCaWArgE7ADGMxAhmuQHQBQoYEnJE8wALKEARnkaxEKdMAC8wAOS0kstGuAAfdQBM8ANzxlRjXQbVaWACwC0JPB0NqA3HwGgIwAJJoWozYHCxixnAsjAhStADmwESMMJYo1Fi4HMCIaPEu+MRklHj8gpqyoeHAAKJFFFTAAN4+giDYCIxwSAByHAR4AFw5SDF5Xm2gJBzdfQPD3WPxE5PAlBxdAPLYNQAelgh4aOHDaPQEMowrIAC+3oJ+AMKMrlrAXFhSAFZ4LEhC9g4-0BmA4JBISXgiCkBQABpILrJ5MhUGhYcATGD6Bk4Hh-jNgABrPDkOBlXyQAAq9ngYmJpOAAHcEOCRjAXqwYODfoo6DhakUSph+Uh7GI4P0xER4Cj0OSQGwMP8tP1hgAlX7swwAHgRl2RvIANALSA08ABtAC6AD4VM1Wm0Kow0MMrYaHYJjGYLLJXZb3at1HYnC43Go-QHQDcvA6-JsmEJXARgCDgMYWAhjIYhDAU+YiMAAFIwex0ZmilMITCGF79TLAGRsAgJYAAZRwSEZGzEABFTOZUrJ5Yn+jwnWgeER6HB7AAKJrADpdXqS4ZqYultTG6azVfqHswPBbtauLY7fayQ7HIbAAAMwBuAEoYw9IBq2Ixs9h2eFMOQYPQObALQKJgggABeYhghCIpikkKRpOQRIknAsZUiIeCttECBEP8NSMCkjDDAARMGziuIYxHwYOjDCMBmDNnAuTxA6irdCOBB1Lh5Dqpqn66tISIykawBnOCtqqC0gbjqc9DgpGkxegOliyfJDrRkAA)\n\n  ```ts\n  // Positions of employees in our company.\n  type MemberPosition = \"intern\" | \"developer\" | \"tech-lead\";\n\n  // Interface describing properties of a single employee.\n  interface Employee {\n    firstName: string;\n    lastName: string;\n    yearsOfExperience: number;\n  }\n\n  // Create an object that has all possible `MemberPosition` values set as keys.\n  // Those keys will store a collection of Employees of the same position.\n  const team: Record\u003cMemberPosition, Employee[]\u003e = {\n    intern: [],\n    developer: [],\n    \"tech-lead\": [],\n  };\n\n  // Our team has decided to help John with his dream of becoming Software Developer.\n  team.intern.push({\n    firstName: \"John\",\n    lastName: \"Doe\",\n    yearsOfExperience: 0,\n  });\n\n  // `Record` forces you to initialize all of the property keys.\n  // TypeScript Error: \"tech-lead\" property is missing\n  const teamEmpty: Record\u003cMemberPosition, null\u003e = {\n    intern: null,\n    developer: null,\n  };\n  ```\n\n  \u003c/details\u003e\n\n- [`Exclude\u003cT, U\u003e`](https://www.typescriptlang.org/docs/handbook/utility-types.html#excludetype-excludedunion) -\n  Exclude from `T` those types that are assignable to `U`.\n  \u003cdetails\u003e\n  \u003csummary\u003e\n  \t\tExample\n  \u003c/summary\u003e\n\n  [Playground](https://typescript-play.js.org/?target=6#code/JYOwLgpgTgZghgYwgAgMrQG7QMIHsQzADmyA3gFDLIAOuUYAXMiAK4A2byAPsgM5hRQJHqwC2AI2gBucgF9y5MAE9qKAEoQAjiwj8AEnBAATNtGQBeZAAooWphu26wAGmS3e93bRC8IASgsAPmRDJRlyAHoI5ABRAA8ENhYjFFYOZGVVZBgoXFFkAAM0zh5+QRBhZhYJaAKAOkjogEkQZAQ4X2QAdwALCFbaemRgXmQtFjhOMFwq9K6ULuB0lk6U+HYwZAxJnQaYFhAEMGB8ZCIIMAAFOjAANR2IK0HGWISklIAedCgsKDwCYgAbQA5M9gQBdVzFQJ+JhiSRQMiUYYwayZCC4VHPCzmSzAspCYEBWxgFhQAZwKC+FpgJ43VwARgADH4ZFQSWSBjcZPJyPtDsdTvxKWBvr8rD1DCZoJ5HPopaYoK4EPhCEQmGKcKriLCtrhgEYkVQVT5Nr4fmZLLZtMBbFZgT0wGBqES6ghbHBIJqoBKFdBWQpjfh+DQbhY2tqiHVsbjLMVkAB+ZAAZiZaeQTHOVxu9ySjxNaujNwDVHNvzqbBGkBAdPoAfkQA)\n\n  ```ts\n  interface ServerConfig {\n    port: null | string | number;\n  }\n\n  type RequestHandler = (request: Request, response: Response) =\u003e void;\n\n  // Exclude `null` type from `null | string | number`.\n  // In case the port is equal to `null`, we will use default value.\n  function getPortValue(port: Exclude\u003cServerConfig[\"port\"], null\u003e): number {\n    if (typeof port === \"string\") {\n      return parseInt(port, 10);\n    }\n\n    return port;\n  }\n\n  function startServer(handler: RequestHandler, config: ServerConfig): void {\n    const server = require(\"http\").createServer(handler);\n\n    const port = config.port === null ? 3000 : getPortValue(config.port);\n    server.listen(port);\n  }\n  ```\n\n  \u003c/details\u003e\n\n- [`Extract\u003cT, U\u003e`](https://www.typescriptlang.org/docs/handbook/utility-types.html#extracttype-union) -\n  Extract from `T` those types that are assignable to `U`.\n  \u003cdetails\u003e\n  \u003csummary\u003e\n  \t\tExample\n  \u003c/summary\u003e\n\n  [Playground](https://typescript-play.js.org/?target=6#code/CYUwxgNghgTiAEAzArgOzAFwJYHtXzSwEdkQBJYACgEoAueVZAWwCMQYBuAKDDwGcM8MgBF4AXngBlAJ6scESgHIRi6ty5ZUGdoihgEABXZ888AN5d48ANoiAuvUat23K6ihMQ9ATE0BzV3goPy8GZjZOLgBfLi4Aejj4AEEICBwAdz54MAALKFQQ+BxEeAAHY1NgKAwoIKy0grr4DByEUpgccpgMaXgAaxBerCzi+B9-ZulygDouFHRsU1z8kKMYE1RhaqgAHkt4AHkWACt4EAAPbVRgLLWNgBp9gGlBs8uQa6yAUUuYPQwdgNpKM7nh7mMML4CgA+R5WABqUAgpDeVxuhxO1he0jsXGh8EoOBO9COx3BQPo2PBADckaR6IjkSA6PBqTgsMBzPsicdrEC7OJWXSQNwYvFEgAVTS9JLXODpeDpKBZFg4GCoWa8VACIJykAKiQWKy2YQOAioYikCg0OEMDyhRSy4DyxS24KhAAMjyi6gS8AAwjh5OD0iBFHAkJoEOksC1mnkMJq8gUQKDNttKPlnfrwYp3J5XfBHXqoKpfYkAOI4ansTxaeDADmoRSCCBYAbxhC6TDx6rwYHIRX5bScjA4bLJwoDmDwDkfbA9JMrVMVdM1TN69LgkTgwgkchUahqIA)\n\n  ```ts\n  declare function uniqueId(): number;\n\n  const ID = Symbol(\"ID\");\n\n  interface Person {\n    [ID]: number;\n    name: string;\n    age: number;\n  }\n\n  // Allows changing the person data as long as the property key is of string type.\n  function changePersonData\u003c\n    Obj extends Person,\n    Key extends Extract\u003ckeyof Person, string\u003e,\n    Value extends Obj[Key]\n  \u003e(obj: Obj, key: Key, value: Value): void {\n    obj[key] = value;\n  }\n\n  // Tiny Andrew was born.\n  const andrew = {\n    [ID]: uniqueId(),\n    name: \"Andrew\",\n    age: 0,\n  };\n\n  // Cool, we're fine with that.\n  changePersonData(andrew, \"name\", \"Pony\");\n\n  // Goverment didn't like the fact that you wanted to change your identity.\n  changePersonData(andrew, ID, uniqueId());\n  ```\n\n  \u003c/details\u003e\n\n- [`NonNullable\u003cT\u003e`](https://www.typescriptlang.org/docs/handbook/utility-types.html#nonnullabletype) -\n  Exclude `null` and `undefined` from `T`.\n  \u003cdetails\u003e\n  \u003csummary\u003e\n  \t\tExample\n  \u003c/summary\u003e\n  Works with \u003ca href=\"https://www.typescriptlang.org/tsconfig#strictNullChecks\"\u003e\u003ccode\u003estrictNullChecks\u003c/code\u003e\u003c/a\u003e set to \u003ccode\u003etrue\u003c/code\u003e.\n\n  [Playground](https://typescript-play.js.org/?target=6#code/C4TwDgpgBACg9gJ2AOQK4FsBGEFQLxQDOwCAlgHYDmUAPlORtrnQwDasDcAUFwPQBU-WAEMkUOADMowqAGNWwwoSgATCBIqlgpOOSjAAFsOBRSy1IQgr9cKJlSlW1mZYQA3HFH68u8xcoBlHA8EACEHJ08Aby4oKDBUTFZSWXjEFEYcAEIALihkXTR2YSSIAB54JDQsHAA+blj4xOTUsHSACkMzPKD3HHDHNQQAGjSkPMqMmoQASh7g-oihqBi4uNIpdraxPAI2VhmVxrX9AzMAOm2ppnwoAA4ABifuE4BfKAhWSyOTuK7CS7pao3AhXF5rV48E4ICDAVAIPT-cGQyG+XTEIgLMJLTx7CAAdygvRCA0iCHaMwarhJOIQjUBSHaACJHk8mYdeLwxtdcVAAOSsh58+lXdr7Dlcq7A3n3J4PEUdADMcspUE53OluAIUGVTx46oAKuAIAFZGQwCYAKIIBCILjUxaDHAMnla+iodjcIA)\n\n  ```ts\n  type PortNumber = string | number | null;\n\n  /** Part of a class definition that is used to build a server */\n  class ServerBuilder {\n    portNumber!: NonNullable\u003cPortNumber\u003e;\n\n    port(this: ServerBuilder, port: PortNumber): ServerBuilder {\n      if (port == null) {\n        this.portNumber = 8000;\n      } else {\n        this.portNumber = port;\n      }\n\n      return this;\n    }\n  }\n\n  const serverBuilder = new ServerBuilder();\n\n  serverBuilder\n    .port(\"8000\") // portNumber = '8000'\n    .port(null) // portNumber =  8000\n    .port(3000); // portNumber =  3000\n\n  // TypeScript error\n  serverBuilder.portNumber = null;\n  ```\n\n  \u003c/details\u003e\n\n- [`Parameters\u003cT\u003e`](https://www.typescriptlang.org/docs/handbook/utility-types.html#parameterstype) -\n  Obtain the parameters of a function type in a tuple.\n  \u003cdetails\u003e\n  \u003csummary\u003e\n  \t\tExample\n  \u003c/summary\u003e\n\n  [Playground](https://typescript-play.js.org/?target=6#code/GYVwdgxgLglg9mABAZwBYmMANgUwBQxgAOIUAXIgIZgCeA2gLoCUFAbnDACaIDeAUIkQB6IYgCypSlBxUATrMo1ECsJzgBbLEoipqAc0J7EMKMgDkiHLnU4wp46pwAPHMgB0fAL58+oSLARECEosLAA5ABUYG2QAHgAxJGdpVWREPDdMylk9ZApqemZEAF4APipacrw-CApEgBogkKwAYThwckQwEHUAIxxZJl4BYVEImiIZKF0oZRwiWVdbeygJmThgOYgcGFYcbhqApCJsyhtpWXcR1cnEePBoeDAABVPzgbTixFeFd8uEsClADcIxGiygIFkSEOT3SmTc2VydQeRx+ZxwF2QQ34gkEwDgsnSuFmMBKiAADEDjIhYk1Qm0OlSYABqZnYka4xA1DJZHJYkGc7yCbyeRA+CAIZCzNAYbA4CIAdxg2zJwVCkWirjwMswuEaACYmCCgA)\n\n  ```ts\n  function shuffle(input: any[]): void {\n    // Mutate array randomly changing its' elements indexes.\n  }\n\n  function callNTimes\u003cFn extends (...args: any[]) =\u003e any\u003e(\n    func: Fn,\n    callCount: number\n  ) {\n    // Type that represents the type of the received function parameters.\n    type FunctionParameters = Parameters\u003cFn\u003e;\n\n    return function (...args: FunctionParameters) {\n      for (let i = 0; i \u003c callCount; i++) {\n        func(...args);\n      }\n    };\n  }\n\n  const shuffleTwice = callNTimes(shuffle, 2);\n  ```\n\n  \u003c/details\u003e\n\n- [`ConstructorParameters\u003cT\u003e`](https://www.typescriptlang.org/docs/handbook/utility-types.html#constructorparameterstype) -\n  Obtain the parameters of a constructor function type in a tuple.\n  \u003cdetails\u003e\n  \u003csummary\u003e\n  \t\tExample\n  \u003c/summary\u003e\n\n  [Playground](https://typescript-play.js.org/?target=6#code/MYGwhgzhAECCBOAXAlqApgWQPYBM0mgG8AoaaFRENALmgkXmQDsBzAblOmCycTV4D8teo1YdO3JiICuwRFngAKClWENmLAJRFOZRAAtkEAHQq00ALzlklNBzIBfYk+KhIMAJJTEYJsDQAwmDA+mgAPAAq0GgAHnxMODCKTGgA7tCKxllg8CwQtL4AngDaALraFgB80EWa1SRkAA6MAG5gfNAB4FABPDJyCrQR9tDNyG0dwMGhtBhgjWEiGgA00F70vv4RhY3hEZXVVinpc42KmuJkkv3y8Bly8EPaDWTkhiZd7r3e8LK3llwGCMXGQWGhEOsfH5zJlsrl8p0+gw-goAAo5MAAW3BaHgEEilU0tEhmzQ212BJ0ry4SOg+kg+gBBiMximIGA0nAfAQLGk2N4EAAEgzYcYcnkLsRdDTvNEYkYUKwSdCme9WdM0MYwYhFPSIPpJdTkAAzDKxBUaZX+aAAQgsVmkCTQxuYaBw2ng4Ok8CYcotSu8pMur09iG9vuObxZnx6SN+AyUWTF8MN0CcZE4Ywm5jZHK5aB5fP4iCFIqT4oRRTKRLo6lYVNeAHpG50wOzOe1zHr9NLQ+HoABybsD4HOKXXRA1JCoKhBELmI5pNaB6Fz0KKBAodDYPAgSUTmqYsAALx4m5nC6nW9nGq14KtaEUA9gR9PvuNCjQ9BgACNvcwNBtAcLiAA)\n\n  ```ts\n  class ArticleModel {\n    title: string;\n    content?: string;\n\n    constructor(title: string) {\n      this.title = title;\n    }\n  }\n\n  class InstanceCache\u003cT extends new (...args: any[]) =\u003e any\u003e {\n    private ClassConstructor: T;\n    private cache: Map\u003cstring, InstanceType\u003cT\u003e\u003e = new Map();\n\n    constructor(ctr: T) {\n      this.ClassConstructor = ctr;\n    }\n\n    getInstance(...args: ConstructorParameters\u003cT\u003e): InstanceType\u003cT\u003e {\n      const hash = this.calculateArgumentsHash(...args);\n\n      const existingInstance = this.cache.get(hash);\n      if (existingInstance !== undefined) {\n        return existingInstance;\n      }\n\n      return new this.ClassConstructor(...args);\n    }\n\n    private calculateArgumentsHash(...args: any[]): string {\n      // Calculate hash.\n      return \"hash\";\n    }\n  }\n\n  const articleCache = new InstanceCache(ArticleModel);\n  const amazonArticle = articleCache.getInstance(\"Amazon forests burining!\");\n  ```\n\n  \u003c/details\u003e\n\n- [`ReturnType\u003cT\u003e`](https://www.typescriptlang.org/docs/handbook/utility-types.html#returntypetype) -\n  Obtain the return type of a function type.\n  \u003cdetails\u003e\n  \u003csummary\u003e\n  \t\tExample\n  \u003c/summary\u003e\n\n  [Playground](https://typescript-play.js.org/?target=6#code/MYGwhgzhAECSAmICmBlJAnAbgS2E6A3gFDTTwD2AcuQC4AW2AdgOYAUAlAFzSbnbyEAvkWFFQkGJSQB3GMVI1sNZNwg10TZgG4S0YOUY0kh1es07d+xmvQBXYDXLpWi5UlMaWAGj0GjJ6BtNdkJdBQYIADpXZGgAXmgYpB1ScOwoq38aeN9DYxoU6GFRKzVoJjUwRjwAYXJbPPRuAFkwAAcAHgAxBodsAx9GWwBbACMMAD4cxhloVraOCyYjdAAzMDxoOut1e0d0UNIZ6WhWSPOwdGYIbiqATwBtAF0uaHudUQB6ACpv6ABpJBINqJdAbADW0Do5BOw3u5R2VTwMHIq2gAANtjZ0bkbHsnFCwJh8ONjHp0EgwEZ4JFoN9PkRVr1FAZoMwkDRYIjqkgOrosepoEgAB7+eAwAV2BxOLy6ACCVxgIrFEoMeOl6AACpcwMMORgIB1JRMiBNWKVdhruJKfOdIpdrtwFddXlzKjyACp3Nq842HaDIbL6BrZBIVGhIpB1EMYSLsmjmtWW-YhAA+qegAAYLKQLQj3ZsEsdccmnGcLor2Dn8xGedHGpEIBzEzspfsfMHDNAANTQACMVaIljV5GQkRA5DYmIpVKQAgAJARO9le33BDXIyi0YuLW2nJFGLqkOvxFB0YPdBSaLZ0IwNzyPkO8-xkGgsLh8Al427a3hWAhXwwHA8EHT5PmgAB1bAQBAANJ24adKWpft72RaBUTgRBUCAj89HAM8xCTaBjggABRQx0DuHJv25P9dCkWRZVIAAiBjoFImpmjlFBgA0NpsjadByDacgIDAEAIAAQmYpjoGYgAZSBsmGPw6DtZiiFA8CoJguDmAQmoZ2QvtUKQLdoAYmBTwgdEiCAA)\n\n  ```ts\n  /** Provides every element of the iterable `iter` into the `callback` function and stores the results in an array. */\n  function mapIter\u003c\n    Elem,\n    Func extends (elem: Elem) =\u003e any,\n    Ret extends ReturnType\u003cFunc\u003e\n  \u003e(iter: Iterable\u003cElem\u003e, callback: Func): Ret[] {\n    const mapped: Ret[] = [];\n\n    for (const elem of iter) {\n      mapped.push(callback(elem));\n    }\n\n    return mapped;\n  }\n\n  const setObject: Set\u003cstring\u003e = new Set();\n  const mapObject: Map\u003cnumber, string\u003e = new Map();\n\n  mapIter(setObject, (value: string) =\u003e value.indexOf(\"Foo\")); // number[]\n\n  mapIter(mapObject, ([key, value]: [number, string]) =\u003e {\n    return key % 2 === 0 ? value : \"Odd\";\n  }); // string[]\n  ```\n\n  \u003c/details\u003e\n\n- [`InstanceType\u003cT\u003e`](https://www.typescriptlang.org/docs/handbook/utility-types.html#instancetypetype) -\n  Obtain the instance type of a constructor function type.\n  \u003cdetails\u003e\n  \u003csummary\u003e\n  \t\tExample\n  \u003c/summary\u003e\n\n  [Playground](https://typescript-play.js.org/?target=6#code/MYGwhgzhAECSAmICmBlJAnAbgS2E6A3gFDTTwD2AcuQC4AW2AdgOYAUAlAFzSbnbyEAvkWFFQkGJSQB3GMVI1sNZNwg10TZgG4S0YOUY0kh1es07d+xmvQBXYDXLpWi5UlMaWAGj0GjJ6BtNdkJdBQYIADpXZGgAXmgYpB1ScOwoq38aeN9DYxoU6GFRKzVoJjUwRjwAYXJbPPRuAFkwAAcAHgAxBodsAx9GWwBbACMMAD4cxhloVraOCyYjdAAzMDxoOut1e0d0UNIZ6WhWSPOwdGYIbiqATwBtAF0uaHudUQB6ACpv6ABpJBINqJdAbADW0Do5BOw3u5R2VTwMHIq2gAANtjZ0bkbHsnFCwJh8ONjHp0EgwEZ4JFoN9PkRVr1FAZoMwkDRYIjqkgOrosepoEgAB7+eAwAV2BxOLy6ACCVxgIrFEoMeOl6AACpcwMMORgIB1JRMiBNWKVdhruJKfOdIpdrtwFddXlzKjyACp3Nq842HaDIbL6BrZBIVGhIpB1EMYSLsmjmtWW-YhAA+qegAAYLKQLQj3ZsEsdccmnGcLor2Dn8xGedHGpEIBzEzspfsfMHDNAANTQACMVaIljV5GQkRA5DYmIpVKQAgAJARO9le33BDXIyi0YuLW2nJFGLqkOvxFB0YPdBSaLZ0IwNzyPkO8-xkGgsLh8Al427a3hWAhXwwHA8EHT5PmgAB1bAQBAANJ24adKWpft72RaBUTgRBUCAj89HAM8xCTaBjggABRQx0DuHJv25P9dCkWRZVIAAiBjoFImpmjlFBgA0NpsjadByDacgIDAEAIAAQmYpjoGYgAZSBsmGPw6DtZiiFA8CoJguDmAQmoZ2QvtUKQLdoAYmBTwgdEiCAA)\n\n  ```ts\n  class IdleService {\n    doNothing(): void {}\n  }\n\n  class News {\n    title: string;\n    content: string;\n\n    constructor(title: string, content: string) {\n      this.title = title;\n      this.content = content;\n    }\n  }\n\n  const instanceCounter: Map\u003cFunction, number\u003e = new Map();\n\n  interface Constructor {\n    new (...args: any[]): any;\n  }\n\n  // Keep track how many instances of `Constr` constructor have been created.\n  function getInstance\u003c\n    Constr extends Constructor,\n    Args extends ConstructorParameters\u003cConstr\u003e\n  \u003e(constructor: Constr, ...args: Args): InstanceType\u003cConstr\u003e {\n    let count = instanceCounter.get(constructor) || 0;\n\n    const instance = new constructor(...args);\n\n    instanceCounter.set(constructor, count + 1);\n\n    console.log(`Created ${count + 1} instances of ${Constr.name} class`);\n\n    return instance;\n  }\n\n  const idleService = getInstance(IdleService);\n  // Will log: `Created 1 instances of IdleService class`\n  const newsEntry = getInstance(\n    News,\n    \"New ECMAScript proposals!\",\n    \"Last month...\"\n  );\n  // Will log: `Created 1 instances of News class`\n  ```\n\n  \u003c/details\u003e\n\n- [`Omit\u003cT, K\u003e`](https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys) -\n  Constructs a type by picking all properties from T and then removing K.\n  \u003cdetails\u003e\n  \u003csummary\u003e\n  \t\tExample\n  \u003c/summary\u003e\n\n  [Playground](https://typescript-play.js.org/?target=6#code/JYOwLgpgTgZghgYwgAgIImAWzgG2QbwChlks4BzCAVShwC5kBnMKUcgbmKYAcIFgIjBs1YgOXMpSFMWbANoBdTiW5woFddwAW0kfKWEAvoUIB6U8gDCUCHEiNkICAHdkYAJ69kz4GC3JcPG4oAHteKDABBxCYNAxsPFBIWEQUCAAPJG4wZABySUFcgJAAEzMLXNV1ck0dIuCw6EjBADpy5AB1FAQ4EGQAV0YUP2AHDy8wEOQbUugmBLwtEIA3OcmQnEjuZBgQqE7gAGtgZAhwKHdkHFGwNvGUdDIcAGUliIBJEF3kAF5kAHlML4ADyPBIAGjyBUYRQAPnkqho4NoYQA+TiEGD9EAISIhPozErQMG4AASK2gn2+AApek9pCSXm8wFSQooAJQMUkAFQAsgAZACiOAgmDOOSIJAQ+OYyGl4DgoDmf2QJRCCH6YvALQQNjsEGFovF1NyJWAy1y7OUyHMyE+yRAuFImG4Iq1YDswHxbRINjA-SgfXlHqVUE4xiAA)\n\n  ```ts\n  interface Animal {\n    imageUrl: string;\n    species: string;\n    images: string[];\n    paragraphs: string[];\n  }\n\n  // Creates new type with all properties of the `Animal` interface\n  // except 'images' and 'paragraphs' properties. We can use this\n  // type to render small hover tooltip for a wiki entry list.\n  type AnimalShortInfo = Omit\u003cAnimal, \"images\" | \"paragraphs\"\u003e;\n\n  function renderAnimalHoverInfo(animals: AnimalShortInfo[]): HTMLElement {\n    const container = document.createElement(\"div\");\n    // Internal implementation.\n    return container;\n  }\n  ```\n\n  \u003c/details\u003e\n\n- [`Uppercase\u003cS extends string\u003e`](https://www.typescriptlang.org/docs/handbook/utility-types.html#uppercasestringtype) -\n  Transforms every character in a string into uppercase.\n  \u003cdetails\u003e\n  \u003csummary\u003e\n  \tExample\n  \u003c/summary\u003e\n\n  ```ts\n  type T = Uppercase\u003c\"hello\"\u003e; // 'HELLO'\n\n  type T2 = Uppercase\u003c\"foo\" | \"bar\"\u003e; // 'FOO' | 'BAR'\n\n  type T3\u003cS extends string\u003e = Uppercase\u003c`aB${S}`\u003e;\n  type T4 = T3\u003c\"xYz\"\u003e; // 'ABXYZ'\n\n  type T5 = Uppercase\u003cstring\u003e; // string\n  type T6 = Uppercase\u003cany\u003e; // any\n  type T7 = Uppercase\u003cnever\u003e; // never\n  type T8 = Uppercase\u003c42\u003e; // Error, type 'number' does not satisfy the constraint 'string'\n  ```\n\n  \u003c/details\u003e\n\n- [`Lowercase\u003cS extends string\u003e`](https://www.typescriptlang.org/docs/handbook/utility-types.html#lowercasestringtype) -\n  Transforms every character in a string into lowercase.\n  \u003cdetails\u003e\n  \u003csummary\u003e\n  \tExample\n  \u003c/summary\u003e\n\n  ```ts\n  type T = Lowercase\u003c\"HELLO\"\u003e; // 'hello'\n\n  type T2 = Lowercase\u003c\"FOO\" | \"BAR\"\u003e; // 'foo' | 'bar'\n\n  type T3\u003cS extends string\u003e = Lowercase\u003c`aB${S}`\u003e;\n  type T4 = T3\u003c\"xYz\"\u003e; // 'abxyz'\n\n  type T5 = Lowercase\u003cstring\u003e; // string\n  type T6 = Lowercase\u003cany\u003e; // any\n  type T7 = Lowercase\u003cnever\u003e; // never\n  type T8 = Lowercase\u003c42\u003e; // Error, type 'number' does not satisfy the constraint 'string'\n  ```\n\n  \u003c/details\u003e\n\n- [`Capitalize\u003cS extends string\u003e`](https://www.typescriptlang.org/docs/handbook/utility-types.html#capitalizestringtype) -\n  Transforms the first character in a string into uppercase.\n  \u003cdetails\u003e\n  \u003csummary\u003e\n  \tExample\n  \u003c/summary\u003e\n\n  ```ts\n  type T = Capitalize\u003c\"hello\"\u003e; // 'Hello'\n\n  type T2 = Capitalize\u003c\"foo\" | \"bar\"\u003e; // 'Foo' | 'Bar'\n\n  type T3\u003cS extends string\u003e = Capitalize\u003c`aB${S}`\u003e;\n  type T4 = T3\u003c\"xYz\"\u003e; // 'ABxYz'\n\n  type T5 = Capitalize\u003cstring\u003e; // string\n  type T6 = Capitalize\u003cany\u003e; // any\n  type T7 = Capitalize\u003cnever\u003e; // never\n  type T8 = Capitalize\u003c42\u003e; // Error, type 'number' does not satisfy the constraint 'string'\n  ```\n\n  \u003c/details\u003e\n\n- [`Uncapitalize\u003cS extends string\u003e`](https://www.typescriptlang.org/docs/handbook/utility-types.html#uncapitalizestringtype) -\n  Transforms the first character in a string into lowercase.\n  \u003cdetails\u003e\n  \u003csummary\u003e\n  \tExample\n  \u003c/summary\u003e\n\n  ```ts\n  type T = Uncapitalize\u003c\"Hello\"\u003e; // 'hello'\n\n  type T2 = Uncapitalize\u003c\"Foo\" | \"Bar\"\u003e; // 'foo' | 'bar'\n\n  type T3\u003cS extends string\u003e = Uncapitalize\u003c`AB${S}`\u003e;\n  type T4 = T3\u003c\"xYz\"\u003e; // 'aBxYz'\n\n  type T5 = Uncapitalize\u003cstring\u003e; // string\n  type T6 = Uncapitalize\u003cany\u003e; // any\n  type T7 = Uncapitalize\u003cnever\u003e; // never\n  type T8 = Uncapitalize\u003c42\u003e; // Error, type 'number' does not satisfy the constraint 'string'\n  ```\n\n  \u003c/details\u003e\n\nYou can find some examples in the\n[TypeScript docs](https://www.typescriptlang.org/docs/handbook/utility-types.html).\n\n## Contribute\n\nContributions welcome! Read the [contribution guidelines](docs/contributing.md)\nfirst.\n\n### Twitter to markdown file\n\nCreate .envrc and fill the value then Use [tweet-to-markdown](https://github.com/kbravh/tweet-to-markdown)\n\n```sh\n# .envrc\nexport TTM_API_KEY=YOUR_API_KEY\n```\n\nThen run the [direnv](https://direnv.net/) command\n\n```sh\n direnv allow .\n```\n\nAnd, generate markdown from a twitter url\n\n```sh\nnpx tweet-to-markdown -p notes https://twitter.com/mattpocockuk/status/1509964736275927042\\?s\\=20\\\u0026t\\=sA-g5MNM5TPjN6Ozs1qxgA\n```\n\nThen save video if available\n\n```sh\nnpx twt-dl-cli@latest https://twitter.com/mattpocockuk/status/1592130978234900484\n```\n\nFinally, add the [Thread Reader App](https://threadreaderapp.com) at the end with below format.\n\n```markdown\n[Thread by @USERNAME on Threadify Reader App](https://threadify.productsway.com/thread/STATUS_ID)\n```\n\nNOTE: I have sent a pull request about this step to `tweet-to-markdown` repository: [feat: add Thread Reader App link and the end #19](https://github.com/kbravh/tweet-to-markdown/pull/19) Might not need this step if this PR is accepted.\n\n## Credits\n\nThis project is made by community and especially the wonderful people and projects listed in this document\n\n### Open Source\n\n- [sindresorhus/type-fest](https://github.com/sindresorhus/type-fest): for 2 sections (Extending existing type, Built-in types)\n- [kbravh/tweet-to-markdown](https://github.com/kbravh/tweet-to-markdown): A command line tool to convert Tweets to Markdown.\n- [jellydn/threadify-plus](https://github.com/jellydn/threadify-plus): ThreadifyPlus is a simple and easy-to-use tool that helps users read and share Twitter threads with ease. (WIP)\n- [egoist/download-twitter-video](https://github.com/egoist/download-twitter-video) : The easiest way to download any Twitter video\n\n### Tech Twitter\n\n- [Matt Pocock ✈️ Modern Frontends](https://twitter.com/mattpocockuk)\n- [Wes Bos](https://twitter.com/wesbos)\n- [Erik Rasmussen](https://twitter.com/erikras)\n- [Carlos Caballero](https://twitter.com/Carlillo)\n- [Ankita Kulkarni](https://twitter.com/kulkarniankita9)\n- [Minko Gechev (@mgechev@mstdn.social)](https://twitter.com/mgechev)\n- [Cory House](https://twitter.com/housecor)\n- [Tomek Sułkowski](https://twitter.com/sulco)\n- [Sebastien Lorber](https://twitter.com/sebastienlorber)\n- [Steve (Builder.io)](https://twitter.com/Steve8708)\n- [StackBlitz](https://twitter.com/StackBlitz)\n\n## Author\n\n👤 **Huynh Duc Dung**\n\n- Website: https://productsway.com/\n- Twitter: [@jellydn](https://twitter.com/jellydn)\n- Github: [@jellydn](https://github.com/jellydn)\n\n## Show your support\n\nGive a ⭐️ if this project helped you!\n\n[![kofi](https://img.shields.io/badge/Ko--fi-F16061?style=for-the-badge\u0026logo=ko-fi\u0026logoColor=white)](https://ko-fi.com/dunghd)\n[![paypal](https://img.shields.io/badge/PayPal-00457C?style=for-the-badge\u0026logo=paypal\u0026logoColor=white)](https://paypal.me/dunghd)\n[![buymeacoffee](https://img.shields.io/badge/Buy_Me_A_Coffee-FFDD00?style=for-the-badge\u0026logo=buy-me-a-coffee\u0026logoColor=black)](https://www.buymeacoffee.com/dunghd)\n\n### Stargazers over time\n\n[![Stargazers over time](https://starchart.cc/jellydn/typescript-tips.svg)](https://starchart.cc/jellydn/typescript-tips)\n","funding_links":["https://github.com/sponsors/jellydn","https://ko-fi.com/dunghd","https://buymeacoffee.com/dunghd","https://polar.sh/jellydn","https://paypal.me/dunghd","https://www.buymeacoffee.com/dunghd"],"categories":["Don't forget to give a :star: to make the project popular","Other Lists","Others"],"sub_categories":["TeX Lists"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjellydn%2Ftypescript-tips","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjellydn%2Ftypescript-tips","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjellydn%2Ftypescript-tips/lists"}