[
  {
    "path": ".changeset/README.md",
    "content": "# Changesets\n\nHello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works\nwith multi-package repos, or single-package repos to help you version and publish your code. You can\nfind the full documentation for it [in our repository](https://github.com/changesets/changesets)\n\nWe have a quick list of common questions to get you started engaging with this project in\n[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)\n"
  },
  {
    "path": ".changeset/config.json",
    "content": "{\n  \"$schema\": \"https://unpkg.com/@changesets/config@2.3.0/schema.json\",\n  \"changelog\": \"@changesets/cli/changelog\",\n  \"commit\": false,\n  \"fixed\": [],\n  \"linked\": [],\n  \"access\": \"public\",\n  \"baseBranch\": \"main\",\n  \"updateInternalDependencies\": \"patch\",\n  \"ignore\": []\n}"
  },
  {
    "path": ".github/workflows/main.yml",
    "content": "name: CI\non:\n  push:\n    branches:\n      - \"**\"\n  pull_request:\n    branches:\n      - \"**\"\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: pnpm/action-setup@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 20.x\n          cache: \"pnpm\"\n\n      - run: pnpm install --frozen-lockfile\n      - run: pnpm run ci\n"
  },
  {
    "path": ".github/workflows/publish.yml",
    "content": "name: Publish\non:\n  push:\n    branches:\n      - \"main\"\n\nconcurrency: ${{ github.workflow }}-${{ github.ref }}\n\njobs:\n  publish:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: pnpm/action-setup@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 20.x\n          cache: \"pnpm\"\n\n      - run: pnpm install --frozen-lockfile\n      - name: Create Release Pull Request or Publish\n        id: changesets\n        uses: changesets/action@v1\n        with:\n          publish: pnpm run release\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\ndist\n.turbo"
  },
  {
    "path": ".npmignore",
    "content": ".changeset\nsrc\nscripts\npnpm-lock.yaml\ntsconfig.json\n.gitignore\n.github\n.changeset\n.turbo\nturbo.json\nog-image.png"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# @total-typescript/ts-reset\n\n## 0.6.1\n\n### Patch Changes\n\n- 757be40: Fixed a bug where creating an empty map would no longer infer types correctly.\n\n## 0.6.0\n\n### Minor Changes\n\n- 6574858: Added a rule, `/map-constructor`, to default `Map` to `Map<unknown, unknown>` when no arguments are passed to the constructor.\n\n  Before, you'd get `any` for both key and value types. Now, the result of `Map.get` is `unknown` instead of `any`:\n\n  ```ts\n  const userMap = new Map();\n\n  const value = userMap.get(\"matt\"); // value: unknown\n  ```\n\n  This now is part of the recommended rules.\n\n- 5bf3a15: Added a rule, `/promise-catch`, to change the `catch` method to take `unknown` instead of `any` as an argument.\n\n  ```ts\n  const promise = Promise.reject(\"error\");\n\n  // BEFORE\n\n  promise.catch((error) => {\n    console.error(error); // error is any!\n  });\n\n  // AFTER\n\n  promise.catch((error) => {\n    console.error(error); // error is unknown!\n  });\n  ```\n\n### Patch Changes\n\n- 53cee4f: author: @none23\n\n  Fixed a bug where running .filter on a union of arrays would not work.\n\n## 0.5.1\n\n### Patch Changes\n\n- Added homepage for npm purposes.\n\n## 0.5.0\n\n### Minor Changes\n\n- 49b8603: Added a rule, `/session`, to make sessionStorage and localStorage safer.\n\n  ```ts\n  // Is now typed as `unknown`, not `any`!\n  localStorage.a;\n\n  // Is now typed as `unknown`, not `any`!\n  sessionStorage.abc;\n  ```\n\n- 49b8603: Added a `/dom` entrypoint to allow users to import DOM-only rules.\n\n## 0.4.1\n\n### Patch Changes\n\n- No changes, just pushing to fix the previous slightly borked release.\n\n## 0.4.0\n\n### Minor Changes\n\n- ce9db42: Added support for widening in `Array.lastIndexOf`, `Array.indexOf`, `ReadonlyArray.lastIndexOf` and `ReadonlyArray.indexOf`.\n- 107dfc2: Changed the array.includes on readonly arrays to NOT be a type predicate. Before this change, this perfectly valid code would not behave correctly.\n\n  ```ts\n  type Code = 0 | 1 | 2;\n  type SpecificCode = 0 | 1;\n\n  const currentCode: Code = 0;\n\n  // Create an empty list of subset type\n  const specificCodeList: ReadonlyArray<SpecificCode> = [];\n\n  // This will be false, since 0 is not in []\n  if (specificCodeList.includes(currentCode)) {\n    currentCode; // -> SpecificCode\n  } else {\n    // This branch will be entered, and ts will think z is 2, when it is actually 0\n    currentCode; // -> 2\n  }\n  ```\n\n  Removing the type predicate brings ts-reset closer towards correctness.\n\n- 4765413: author: @mefechoel\n\n  Added the `Map.has` rule.\n\n  Similar to `.includes` or `Set.has()`, `Map.has()` doesn't let you pass members that don't exist in the map's keys:\n\n  ```ts\n  // BEFORE\n  const userMap = new Map([\n    [\"matt\", 0],\n    [\"sofia\", 1],\n    [2, \"waqas\"],\n  ] as const);\n\n  // Argument of type '\"bryan\"' is not assignable to\n  // parameter of type '\"matt\" | \"sofia\" | \"waqas\"'.\n  userMap.has(\"bryan\");\n  ```\n\n  With the rule enabled, `Map` follows the same semantics as `Set`.\n\n  ```ts\n  // AFTER\n  import \"@total-typescript/ts-reset/map-has\";\n\n  const userMap = new Map([\n    [\"matt\", 0],\n    [\"sofia\", 1],\n    [2, \"waqas\"],\n  ] as const);\n\n  // .has now takes a string as the argument!\n  userMap.has(\"bryan\");\n  ```\n\n### Patch Changes\n\n- b15aaa4: Fixed an oversight with the initial `set-has` implementation by adding support to `ReadonlySet`.\n\n## 0.3.7\n\n### Patch Changes\n\n- Added license and switched to MIT\n\n## 0.3.6\n\n### Patch Changes\n\n- d3ddefa: Changed the exports map so \"types\" appears top\n\n## 0.3.5\n\n### Patch Changes\n\n- Another fix for deploy process.\n\n## 0.3.4\n\n### Patch Changes\n\n- Fixed an issue where dist folder was not deployed.\n\n## 0.3.3\n\n### Patch Changes\n\n- Fixed a bug where 0n was not being filtered out by filter-boolean\n\n## 0.3.2\n\n### Patch Changes\n\n- Removed the ability to use Set.has as a type predicate. This ensures that Set.has never sets the checked element to never.\n\n## 0.3.1\n\n### Patch Changes\n\n- Fixed a bug where Array.includes was returning a predicate, which gave false positives.\n\n## 0.3.0\n\n### Minor Changes\n\n- ed9edc1: Added improved typings for Set.has\n\n### Patch Changes\n\n- d27e819: Fixed issue where webpack wasn't recognizing the exports map\n\n## 0.2.1\n\n### Patch Changes\n\n- Readme tweak\n\n## 0.2.0\n\n### Minor Changes\n\n- e5a33c9: Added support for array.includes\n\n### Patch Changes\n\n- 8fe8e29: Improved filter-boolean to handle falsy values, not just NonNullable values\n\n## 0.1.4\n\n### Patch Changes\n\n- Fixed exports (finally)\n\n## 0.1.3\n\n### Patch Changes\n\n- bb3f2d1: Attempted fix for exports maps\n\n## 0.1.2\n\n### Patch Changes\n\n- 4cfb07e: Fixed build process and moved to .d.ts files\n\n## 0.1.1\n\n### Patch Changes\n\n- 0360275: Fixed type imports\n- e62b05a: Added .npmignore\n\n## 0.1.0\n\n### Minor Changes\n\n- 51628fc: Initial commit\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright 2023 Matthew Pocock\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"@total-typescript/ts-reset\",\n  \"version\": \"0.6.1\",\n  \"description\": \"A CSS reset for TypeScript, improving types for common JavaScript API's\",\n  \"private\": false,\n  \"repository\": \"https://github.com/total-typescript/ts-reset\",\n  \"homepage\": \"https://totaltypescript.com/ts-reset\",\n  \"scripts\": {\n    \"dev\": \"tsc --watch\",\n    \"build\": \"tsx scripts/build.ts\",\n    \"ci\": \"turbo build check-exports lint lint-pkg-json format:check\",\n    \"check-exports\": \"check-export-map\",\n    \"lint\": \"tsc\",\n    \"lint-pkg-json\": \"tsx scripts/lint.ts\",\n    \"release\": \"turbo run publish\",\n    \"publish\": \"changeset publish\",\n    \"format:check\": \"prettier  \\\"./src/**/**.ts\\\" --check\",\n    \"format\": \"prettier --write \\\"./src/**/**.ts\\\" --write\"\n  },\n  \"main\": \"./dist/recommended.js\",\n  \"module\": \"./dist/recommended.mjs\",\n  \"types\": \"./dist/recommended.d.ts\",\n  \"exports\": {\n    \"./package.json\": \"./package.json\",\n    \".\": {\n      \"types\": \"./dist/recommended.d.ts\",\n      \"import\": \"./dist/recommended.mjs\",\n      \"default\": \"./dist/recommended.js\"\n    },\n    \"./recommended\": {\n      \"types\": \"./dist/recommended.d.ts\",\n      \"import\": \"./dist/recommended.mjs\",\n      \"default\": \"./dist/recommended.js\"\n    },\n    \"./filter-boolean\": {\n      \"types\": \"./dist/filter-boolean.d.ts\",\n      \"import\": \"./dist/filter-boolean.mjs\",\n      \"default\": \"./dist/filter-boolean.js\"\n    },\n    \"./is-array\": {\n      \"types\": \"./dist/is-array.d.ts\",\n      \"import\": \"./dist/is-array.mjs\",\n      \"default\": \"./dist/is-array.js\"\n    },\n    \"./json-parse\": {\n      \"types\": \"./dist/json-parse.d.ts\",\n      \"import\": \"./dist/json-parse.mjs\",\n      \"default\": \"./dist/json-parse.js\"\n    },\n    \"./fetch\": {\n      \"types\": \"./dist/fetch.d.ts\",\n      \"import\": \"./dist/fetch.mjs\",\n      \"default\": \"./dist/fetch.js\"\n    },\n    \"./array-includes\": {\n      \"types\": \"./dist/array-includes.d.ts\",\n      \"import\": \"./dist/array-includes.mjs\",\n      \"default\": \"./dist/array-includes.js\"\n    },\n    \"./set-has\": {\n      \"types\": \"./dist/set-has.d.ts\",\n      \"import\": \"./dist/set-has.mjs\",\n      \"default\": \"./dist/set-has.js\"\n    },\n    \"./promise-catch\": {\n      \"types\": \"./dist/promise-catch.d.ts\",\n      \"import\": \"./dist/promise-catch.mjs\",\n      \"default\": \"./dist/promise-catch.js\"\n    },\n    \"./map-constructor\": {\n      \"types\": \"./dist/map-constructor.d.ts\",\n      \"import\": \"./dist/map-constructor.mjs\",\n      \"default\": \"./dist/map-constructor.js\"\n    },\n    \"./map-has\": {\n      \"types\": \"./dist/map-has.d.ts\",\n      \"import\": \"./dist/map-has.mjs\",\n      \"default\": \"./dist/map-has.js\"\n    },\n    \"./utils\": {\n      \"types\": \"./dist/utils.d.ts\",\n      \"import\": \"./dist/utils.mjs\",\n      \"default\": \"./dist/utils.js\"\n    },\n    \"./array-index-of\": {\n      \"types\": \"./dist/array-index-of.d.ts\",\n      \"import\": \"./dist/array-index-of.mjs\",\n      \"default\": \"./dist/array-index-of.js\"\n    },\n    \"./dom\": {\n      \"types\": \"./dist/dom.d.ts\",\n      \"import\": \"./dist/dom.mjs\",\n      \"default\": \"./dist/dom.js\"\n    },\n    \"./storage\": {\n      \"types\": \"./dist/storage.d.ts\",\n      \"import\": \"./dist/storage.mjs\",\n      \"default\": \"./dist/storage.js\"\n    }\n  },\n  \"keywords\": [],\n  \"author\": \"Matt Pocock\",\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"@changesets/cli\": \"^2.27.3\",\n    \"@types/node\": \"^18.19.33\",\n    \"check-export-map\": \"^1.3.1\",\n    \"prettier\": \"^3.2.5\",\n    \"tsx\": \"^3.14.0\",\n    \"turbo\": \"^1.13.3\",\n    \"typescript\": \"^5.5.4\"\n  },\n  \"prettier\": {\n    \"arrowParens\": \"always\",\n    \"trailingComma\": \"all\",\n    \"semi\": true,\n    \"printWidth\": 80,\n    \"singleQuote\": false,\n    \"tabWidth\": 2,\n    \"useTabs\": false\n  },\n  \"packageManager\": \"pnpm@9.7.1+sha512.faf344af2d6ca65c4c5c8c2224ea77a81a5e8859cbc4e06b1511ddce2f0151512431dd19e6aff31f2c6a8f5f2aced9bd2273e1fed7dd4de1868984059d2c4247\"\n}\n"
  },
  {
    "path": "readme.md",
    "content": "![TS Reset - Improved TypeScript's Built-in Typings](https://raw.githubusercontent.com/mattpocock/ts-reset/main/og-image.png)\n\n**Without `ts-reset`**:\n\n- 🚨 `.json` (in `fetch`) and `JSON.parse` both return `any`\n- 🤦 `.filter(Boolean)` doesn't behave how you expect\n- 😡 `array.includes` often breaks on readonly arrays\n\n`ts-reset` smooths over these hard edges, just like a CSS reset does in the browser.\n\n**With `ts-reset`**:\n\n- 👍 `.json` (in `fetch`) and `JSON.parse` both return `unknown`\n- ✅ `.filter(Boolean)` behaves EXACTLY how you expect\n- 🥹 `array.includes` is widened to be more ergonomic\n- 🚀 And several more changes!\n\n## Official Docs\n\nCheck out our docs page on [Total TypeScript](https://totaltypescript.com/ts-reset)\n"
  },
  {
    "path": "scripts/build.ts",
    "content": "import * as fs from \"fs/promises\";\nimport * as path from \"path\";\n\nconst entrypointDir = path.join(__dirname, \"../\", \"src\", \"entrypoints\");\nconst distDir = path.join(__dirname, \"../\", \"dist\");\n\nconst run = async () => {\n  try {\n    await fs.mkdir(distDir);\n  } catch (e) {}\n\n  const entrypoints = await fs.readdir(entrypointDir);\n\n  for (const entrypoint of entrypoints) {\n    const entrypointBase = entrypoint.replace(\".d.ts\", \"\");\n\n    await Promise.all([\n      fs.writeFile(path.join(distDir, `${entrypointBase}.js`), \"\"),\n      fs.writeFile(path.join(distDir, `${entrypointBase}.mjs`), \"\"),\n      fs.copyFile(\n        path.join(entrypointDir, entrypoint),\n        path.join(distDir, `${entrypointBase}.d.ts`),\n      ),\n    ]);\n  }\n};\n\nrun().catch((e) => {\n  console.error(e);\n  process.exit(1);\n});\n"
  },
  {
    "path": "scripts/lint.ts",
    "content": "import * as fs from \"fs\";\nimport * as path from \"path\";\n\nconst packageJsonContents = fs.readFileSync(\n  path.join(__dirname, \"../\", \"package.json\"),\n  \"utf8\",\n);\n\nconst packageJson = JSON.parse(packageJsonContents) as {\n  exports: Record<string, any>;\n};\n\nconst pkgJsonExports = Object.keys(packageJson.exports).filter((entrypoint) => {\n  return entrypoint !== \".\"; // ignore the root entrypoint\n});\n\nconst entrypointFiles = fs\n  .readdirSync(path.join(__dirname, \"../src/entrypoints\"))\n  .map((file) => {\n    return file.replace(\".d.ts\", \"\");\n  });\n\nfor (const entrypointFile of entrypointFiles) {\n  if (!pkgJsonExports.includes(`./${entrypointFile}`)) {\n    console.error(\n      `Missing export file in package.json for ./src/entrypoints/${entrypointFile}.ts`,\n    );\n\n    process.exit(1);\n  }\n}\n"
  },
  {
    "path": "src/entrypoints/array-includes.d.ts",
    "content": "/// <reference path=\"utils.d.ts\" />\n\ninterface ReadonlyArray<T> {\n  includes(\n    searchElement: T | (TSReset.WidenLiteral<T> & {}),\n    fromIndex?: number,\n  ): boolean;\n}\n\ninterface Array<T> {\n  includes(\n    searchElement: T | (TSReset.WidenLiteral<T> & {}),\n    fromIndex?: number,\n  ): boolean;\n}\n"
  },
  {
    "path": "src/entrypoints/array-index-of.d.ts",
    "content": "/// <reference path=\"utils.d.ts\" />\n\ninterface ReadonlyArray<T> {\n  lastIndexOf(\n    searchElement: T | (TSReset.WidenLiteral<T> & {}),\n    fromIndex?: number,\n  ): number;\n  indexOf(\n    searchElement: T | (TSReset.WidenLiteral<T> & {}),\n    fromIndex?: number,\n  ): number;\n}\n\ninterface Array<T> {\n  lastIndexOf(\n    searchElement: T | (TSReset.WidenLiteral<T> & {}),\n    fromIndex?: number,\n  ): number;\n  indexOf(\n    searchElement: T | (TSReset.WidenLiteral<T> & {}),\n    fromIndex?: number,\n  ): number;\n}\n"
  },
  {
    "path": "src/entrypoints/dom.d.ts",
    "content": "/// <reference path=\"recommended.d.ts\" />\n/// <reference path=\"storage.d.ts\" />\n"
  },
  {
    "path": "src/entrypoints/fetch.d.ts",
    "content": "interface Body {\n  json(): Promise<unknown>;\n}\n"
  },
  {
    "path": "src/entrypoints/filter-boolean.d.ts",
    "content": "/// <reference path=\"utils.d.ts\" />\n\ninterface Array<T> {\n  filter<S extends T>(\n    predicate: BooleanConstructor,\n    thisArg?: any,\n  ): TSReset.NonFalsy<S>[];\n}\n\ninterface ReadonlyArray<T> {\n  filter<S extends T>(\n    predicate: BooleanConstructor,\n    thisArg?: any,\n  ): TSReset.NonFalsy<S>[];\n}\n"
  },
  {
    "path": "src/entrypoints/is-array.d.ts",
    "content": "interface ArrayConstructor {\n  isArray(arg: any): arg is unknown[];\n}\n"
  },
  {
    "path": "src/entrypoints/json-parse.d.ts",
    "content": "interface JSON {\n  /**\n   * Converts a JavaScript Object Notation (JSON) string into an object.\n   * @param text A valid JSON string.\n   * @param reviver A function that transforms the results. This function is called for each member of the object.\n   * If a member contains nested objects, the nested objects are transformed before the parent object is.\n   */\n  parse(\n    text: string,\n    reviver?: (this: any, key: string, value: any) => any,\n  ): unknown;\n}\n"
  },
  {
    "path": "src/entrypoints/map-constructor.d.ts",
    "content": "interface MapConstructor {\n  new <K = unknown, V = unknown>(): Map<K, V>;\n}\n"
  },
  {
    "path": "src/entrypoints/map-has.d.ts",
    "content": "/// <reference path=\"utils.d.ts\" />\n\ninterface Map<K, V> {\n  has(value: K | (TSReset.WidenLiteral<K> & {})): boolean;\n}\n\ninterface ReadonlyMap<K, V> {\n  has(value: K | (TSReset.WidenLiteral<K> & {})): boolean;\n}\n"
  },
  {
    "path": "src/entrypoints/promise-catch.d.ts",
    "content": "interface Promise<T> {\n  /**\n   * Attaches callbacks for the resolution and/or rejection of the Promise.\n   * @param onfulfilled The callback to execute when the Promise is resolved.\n   * @param onrejected The callback to execute when the Promise is rejected.\n   * @returns A Promise for the completion of which ever callback is executed.\n   */\n  then<TResult1 = T, TResult2 = never>(\n    onfulfilled?:\n      | ((value: T) => TResult1 | PromiseLike<TResult1>)\n      | undefined\n      | null,\n    onrejected?:\n      | ((reason: unknown) => TResult2 | PromiseLike<TResult2>)\n      | undefined\n      | null,\n  ): Promise<TResult1 | TResult2>;\n\n  /**\n   * Attaches a callback for only the rejection of the Promise.\n   * @param onrejected The callback to execute when the Promise is rejected.\n   * @returns A Promise for the completion of the callback.\n   */\n  catch<TResult = never>(\n    onrejected?:\n      | ((reason: unknown) => TResult | PromiseLike<TResult>)\n      | undefined\n      | null,\n  ): Promise<T | TResult>;\n}\n"
  },
  {
    "path": "src/entrypoints/recommended.d.ts",
    "content": "/// <reference path=\"fetch.d.ts\" />\n/// <reference path=\"filter-boolean.d.ts\" />\n/// <reference path=\"is-array.d.ts\" />\n/// <reference path=\"json-parse.d.ts\" />\n/// <reference path=\"array-includes.d.ts\" />\n/// <reference path=\"set-has.d.ts\" />\n/// <reference path=\"map-constructor.d.ts\" />\n/// <reference path=\"map-has.d.ts\" />\n/// <reference path=\"array-index-of.d.ts\" />\n/// <reference path=\"promise-catch.d.ts\" />\n"
  },
  {
    "path": "src/entrypoints/set-has.d.ts",
    "content": "/// <reference path=\"utils.d.ts\" />\n\ninterface Set<T> {\n  has(value: T | (TSReset.WidenLiteral<T> & {})): boolean;\n}\n\ninterface ReadonlySet<T> {\n  has(value: T | (TSReset.WidenLiteral<T> & {})): boolean;\n}\n"
  },
  {
    "path": "src/entrypoints/storage.d.ts",
    "content": "interface Storage {\n  [name: string & {}]: unknown;\n}\n"
  },
  {
    "path": "src/entrypoints/utils.d.ts",
    "content": "declare namespace TSReset {\n  type NonFalsy<T> = T extends false | 0 | \"\" | null | undefined | 0n\n    ? never\n    : T;\n\n  type WidenLiteral<T> = T extends string\n    ? string\n    : T extends number\n      ? number\n      : T extends boolean\n        ? boolean\n        : T extends bigint\n          ? bigint\n          : T extends symbol\n            ? symbol\n            : T;\n}\n"
  },
  {
    "path": "src/tests/array-includes.ts",
    "content": "import { doNotExecute, Equal, Expect } from \"./utils\";\n\ndoNotExecute(async () => {\n  const arr = [\"1\", \"2\", \"3\"] as const;\n\n  // Look ma, no error!\n  arr.includes(\"4\");\n\n  // Look ma, proper errors!\n  arr.includes(\n    // @ts-expect-error\n    2,\n  );\n  arr.includes(\n    // @ts-expect-error\n    true,\n  );\n});\n\ndoNotExecute(async () => {\n  const arr = [1, 2, 3] as const;\n\n  arr.includes(4);\n  arr.includes(\n    // @ts-expect-error\n    true,\n  );\n  arr.includes(\n    // @ts-expect-error\n    \"str\",\n  );\n});\n\ndoNotExecute(async () => {\n  const arr = [\n    { a: 1 },\n    {\n      a: 2,\n    },\n    {\n      a: 3,\n    },\n  ] as const;\n\n  arr.includes(\n    // @ts-expect-error\n    4,\n  );\n\n  arr.includes({ a: 1 });\n});\n\ndoNotExecute(async () => {\n  const arr: Array<\"1\" | \"2\" | \"3\"> = [\"1\", \"2\", \"3\"];\n\n  arr.includes(\"4\");\n\n  arr.includes(\n    // @ts-expect-error\n    2,\n  );\n  arr.includes(\n    // @ts-expect-error\n    true,\n  );\n});\n"
  },
  {
    "path": "src/tests/array-index-of.ts",
    "content": "import { doNotExecute, Equal, Expect } from \"./utils\";\n\ndoNotExecute(async () => {\n  const arr = [\"1\", \"2\", \"3\"] as const;\n\n  // Look ma, no error!\n  arr.indexOf(\"4\");\n\n  // Look ma, proper errors!\n  arr.indexOf(\n    // @ts-expect-error\n    2,\n  );\n  arr.indexOf(\n    // @ts-expect-error\n    true,\n  );\n});\n\ndoNotExecute(async () => {\n  const arr = [1, 2, 3] as const;\n\n  arr.indexOf(4);\n  arr.indexOf(\n    // @ts-expect-error\n    true,\n  );\n  arr.indexOf(\n    // @ts-expect-error\n    \"str\",\n  );\n});\n\ndoNotExecute(async () => {\n  const arr = [\n    { a: 1 },\n    {\n      a: 2,\n    },\n    {\n      a: 3,\n    },\n  ] as const;\n\n  arr.indexOf(\n    // @ts-expect-error\n    4,\n  );\n\n  arr.indexOf({ a: 1 });\n});\n\ndoNotExecute(async () => {\n  const arr: Array<\"1\" | \"2\" | \"3\"> = [\"1\", \"2\", \"3\"];\n\n  arr.indexOf(\"4\");\n\n  arr.indexOf(\n    // @ts-expect-error\n    2,\n  );\n  arr.indexOf(\n    // @ts-expect-error\n    true,\n  );\n});\n\ndoNotExecute(() => {\n  const arr: string[] | number[] = {} as any;\n\n  const result = arr.indexOf(\"abc\");\n});\n\n// lastIndexOf\n\ndoNotExecute(async () => {\n  const arr = [\"1\", \"2\", \"3\"] as const;\n\n  // Look ma, no error!\n  arr.lastIndexOf(\"4\");\n\n  // Look ma, proper errors!\n  arr.lastIndexOf(\n    // @ts-expect-error\n    2,\n  );\n  arr.lastIndexOf(\n    // @ts-expect-error\n    true,\n  );\n});\n\ndoNotExecute(async () => {\n  const arr = [1, 2, 3] as const;\n\n  arr.lastIndexOf(4);\n  arr.lastIndexOf(\n    // @ts-expect-error\n    true,\n  );\n  arr.lastIndexOf(\n    // @ts-expect-error\n    \"str\",\n  );\n});\n\ndoNotExecute(async () => {\n  const arr = [\n    { a: 1 },\n    {\n      a: 2,\n    },\n    {\n      a: 3,\n    },\n  ] as const;\n\n  arr.lastIndexOf(\n    // @ts-expect-error\n    4,\n  );\n\n  arr.lastIndexOf({ a: 1 });\n});\n\ndoNotExecute(async () => {\n  const arr: Array<\"1\" | \"2\" | \"3\"> = [\"1\", \"2\", \"3\"];\n\n  arr.lastIndexOf(\"4\");\n\n  arr.lastIndexOf(\n    // @ts-expect-error\n    2,\n  );\n  arr.lastIndexOf(\n    // @ts-expect-error\n    true,\n  );\n});\n\ndoNotExecute(() => {\n  const arr: string[] | number[] = {} as any;\n\n  const result = arr.lastIndexOf(\"abc\");\n});\n"
  },
  {
    "path": "src/tests/fetch.ts",
    "content": "import { doNotExecute, Equal, Expect } from \"./utils\";\n\ndoNotExecute(async () => {\n  const result = await fetch(\"/\").then((res) => res.json());\n\n  type tests = [Expect<Equal<typeof result, unknown>>];\n});\n\ndoNotExecute(async () => {\n  // Make tests fail when someone tries to PR res.json<T>\n\n  const result = await fetch(\"/\").then((res) => {\n    // @ts-expect-error\n    return res.json<string>();\n  });\n});\n"
  },
  {
    "path": "src/tests/filter-boolean.ts",
    "content": "import { doNotExecute, Equal, Expect } from \"./utils\";\n\ndoNotExecute(() => {\n  const arr = [1, 2, 3, undefined];\n\n  const result = arr.filter(Boolean);\n\n  type tests = [Expect<Equal<typeof result, number[]>>];\n});\n\ndoNotExecute(() => {\n  const arr = [\"1\", \"2\", undefined] as const;\n\n  const result = arr.filter(Boolean);\n\n  type tests = [Expect<Equal<typeof result, (\"1\" | \"2\")[]>>];\n});\n\ndoNotExecute(() => {\n  const arr = [0, null, undefined, false, \"\"] as const;\n\n  const result = arr.filter(Boolean);\n\n  type tests = [Expect<Equal<typeof result, never[]>>];\n});\n\ndoNotExecute(() => {\n  const arr: (0 | null | undefined | false | \"\" | 0n)[] = [\n    0,\n    null,\n    undefined,\n    false,\n    \"\",\n    0n,\n  ];\n\n  const result = arr.filter(Boolean);\n\n  type tests = [Expect<Equal<typeof result, never[]>>];\n});\n\ndoNotExecute(() => {\n  const arr: string[] | number[] = {} as any;\n\n  const result = arr.filter((x) => typeof x === \"string\");\n\n  type tests = [Expect<Equal<typeof result, string[]>>];\n});\n"
  },
  {
    "path": "src/tests/is-array.ts",
    "content": "import { doNotExecute, Equal, Expect } from \"./utils\";\n\ndoNotExecute(() => {\n  const maybeArr = [1, 2, 3] as unknown;\n\n  if (Array.isArray(maybeArr)) {\n    type tests = [Expect<Equal<typeof maybeArr, unknown[]>>];\n  }\n});\n\ndoNotExecute(() => {\n  const arrOrString = [] as string[] | string;\n\n  if (Array.isArray(arrOrString)) {\n    type tests = [Expect<Equal<typeof arrOrString, string[]>>];\n  }\n});\n\ndoNotExecute(() => {\n  let path: string | string[] = [];\n\n  const paths = Array.isArray(path) ? path : [path];\n\n  type tests = [Expect<Equal<typeof paths, string[]>>];\n});\n"
  },
  {
    "path": "src/tests/json-parse.ts",
    "content": "import { doNotExecute, Equal, Expect } from \"./utils\";\n\ndoNotExecute(() => {\n  const result = JSON.parse(\"{}\");\n\n  type tests = [Expect<Equal<typeof result, unknown>>];\n});\n\ndoNotExecute(() => {\n  // Make tests fail when someone tries to PR JSON.parse<T>\n\n  // @ts-expect-error\n  const result = JSON.parse<string>(\"{}\");\n});\n"
  },
  {
    "path": "src/tests/map-constructor.ts",
    "content": "import { doNotExecute, Equal, Expect } from \"./utils\";\n\ndoNotExecute(() => {\n  const map = new Map();\n\n  const result = map.get(\"foo\");\n\n  type test = [Expect<Equal<typeof result, unknown>>];\n});\n\ndoNotExecute(() => {\n  const map = new Map();\n\n  map.set(\"Jessie\", { phone: \"213-555-1234\", address: \"123 N 1st Ave\" });\n\n  const result = map.has(\"Jessie\");\n\n  type test = [Expect<Equal<typeof result, boolean>>];\n});\n\ndoNotExecute(() => {\n  const map = new Map();\n\n  map.set(\"Jessie\", { phone: \"213-555-1234\", address: \"123 N 1st Ave\" });\n\n  const result = map.get(\"Jessie\");\n\n  type test = [Expect<Equal<typeof result, unknown>>];\n});\n\ndoNotExecute(() => {\n  const map = new Map();\n\n  map.set(\"Jessie\", { phone: \"213-555-1234\", address: \"123 N 1st Ave\" });\n\n  const result = map.delete(\"Jessie\");\n\n  type test = [Expect<Equal<typeof result, boolean>>];\n});\n\ndoNotExecute(() => {\n  const map = new Map();\n\n  map.set(\"Jessie\", { phone: \"213-555-1234\", address: \"123 N 1st Ave\" });\n  map.set(\"Hilary\", { phone: \"617-555-4321\", address: \"321 S 2nd St\" });\n\n  const size = map.size;\n\n  type testSize = [Expect<Equal<typeof size, number>>];\n});\n\ndoNotExecute(() => {\n  const map = new Map();\n\n  map.set(\"Jessie\", { phone: \"213-555-1234\", address: \"123 N 1st Ave\" });\n  map.set(\"Hilary\", { phone: \"617-555-4321\", address: \"321 S 2nd St\" });\n\n  const cleared = map.clear();\n\n  type testClear = [Expect<Equal<typeof cleared, void>>];\n});\n\ndoNotExecute(() => {\n  const map = new Map() satisfies Map<string, boolean>;\n  type test = [Expect<Equal<typeof map, Map<string, boolean>>>];\n});\n\ndoNotExecute(() => {\n  const map: Map<string, boolean> = new Map();\n  type test = [Expect<Equal<typeof map, Map<string, boolean>>>];\n});\n\ndoNotExecute(() => {\n  function expectsBooleanMap(map: Map<string, boolean>) {\n    return map;\n  }\n  const map = expectsBooleanMap(new Map());\n  type test = [Expect<Equal<typeof map, Map<string, boolean>>>];\n});\n\ndoNotExecute(() => {\n  const map = new Map([\n    [\"foo\", 1],\n    [\"bar\", 2],\n  ]);\n  type test = [Expect<Equal<typeof map, Map<string, number>>>];\n});\n"
  },
  {
    "path": "src/tests/map-has.ts",
    "content": "import { doNotExecute } from \"./utils\";\n\ndoNotExecute(() => {\n  const map = new Map([\n    [1, \"1\"],\n    [2, \"2\"],\n    [3, \"3\"],\n  ] as const);\n\n  map.has(4);\n\n  map.has(\n    // @ts-expect-error\n    \"4\",\n  );\n\n  map.has(\n    // @ts-expect-error\n    true,\n  );\n});\n\ndoNotExecute(() => {\n  const map = new Map([\n    [1, \"1\"],\n    [2, \"2\"],\n    [3, \"3\"],\n  ] as const) as ReadonlyMap<1 | 2 | 3, \"1\" | \"2\" | \"3\">;\n\n  map.has(4);\n\n  map.has(\n    // @ts-expect-error\n    \"4\",\n  );\n\n  map.has(\n    // @ts-expect-error\n    true,\n  );\n});\n"
  },
  {
    "path": "src/tests/promise-catch.ts",
    "content": "import { doNotExecute, Equal, Expect } from \"./utils\";\n\ndoNotExecute(async () => {\n  Promise.reject(\"string instead of Error\").catch((err) => {\n    type test = Expect<Equal<unknown, typeof err>>;\n  });\n\n  Promise.reject(\"string instead of Error\").then(\n    () => {},\n    (err) => {\n      type test = Expect<Equal<unknown, typeof err>>;\n    },\n  );\n});\n"
  },
  {
    "path": "src/tests/set-has.ts",
    "content": "import { doNotExecute, Equal, Expect } from \"./utils\";\n\ndoNotExecute(() => {\n  const set = new Set([1, 2, 3] as const);\n\n  set.has(4);\n\n  set.has(\n    // @ts-expect-error\n    \"4\",\n  );\n\n  set.has(\n    // @ts-expect-error\n    true,\n  );\n});\n\ndoNotExecute(() => {\n  const set = new Set([1, 2, 3] as const) as ReadonlySet<1 | 2 | 3>;\n\n  set.has(4);\n\n  set.has(\n    // @ts-expect-error\n    \"4\",\n  );\n\n  set.has(\n    // @ts-expect-error\n    true,\n  );\n});\n"
  },
  {
    "path": "src/tests/storage.ts",
    "content": "import { doNotExecute, Equal, Expect } from \"./utils\";\n\n// Ensure that arbitrary access to localStorage is not allowed\ndoNotExecute(() => {\n  type test = Expect<Equal<typeof localStorage.a, unknown>>;\n\n  // @ts-expect-error\n  localStorage.a.b.c;\n});\n\n// Ensure that the type of localStorage remains correct\ndoNotExecute(() => {\n  type tests = [\n    Expect<Equal<typeof localStorage.getItem, (key: string) => string | null>>,\n    Expect<\n      Equal<typeof localStorage.setItem, (key: string, value: string) => void>\n    >,\n    Expect<Equal<typeof localStorage.removeItem, (key: string) => void>>,\n    Expect<Equal<typeof localStorage.clear, () => void>>,\n    Expect<Equal<typeof localStorage.key, (index: number) => string | null>>,\n    Expect<Equal<typeof localStorage.length, number>>,\n  ];\n});\n\n// Ensure that arbitrary access to sessionStorage is not allowed\ndoNotExecute(() => {\n  type test = Expect<Equal<typeof sessionStorage.a, unknown>>;\n\n  // @ts-expect-error\n  sessionStorage.a.b.c;\n});\n\n// Ensure that the type of sessionStorage remains correct\ndoNotExecute(() => {\n  type tests = [\n    Expect<\n      Equal<typeof sessionStorage.getItem, (key: string) => string | null>\n    >,\n    Expect<\n      Equal<typeof sessionStorage.setItem, (key: string, value: string) => void>\n    >,\n    Expect<Equal<typeof sessionStorage.removeItem, (key: string) => void>>,\n    Expect<Equal<typeof sessionStorage.clear, () => void>>,\n    Expect<Equal<typeof sessionStorage.key, (index: number) => string | null>>,\n    Expect<Equal<typeof sessionStorage.length, number>>,\n  ];\n});\n"
  },
  {
    "path": "src/tests/utils.ts",
    "content": "export type Expect<T extends true> = T;\nexport type ExpectTrue<T extends true> = T;\nexport type ExpectFalse<T extends false> = T;\nexport type IsTrue<T extends true> = T;\nexport type IsFalse<T extends false> = T;\n\nexport type Equal<X, Y> =\n  (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2\n    ? true\n    : false;\nexport type NotEqual<X, Y> = true extends Equal<X, Y> ? false : true;\n\n// https://stackoverflow.com/questions/49927523/disallow-call-with-any/49928360#49928360\nexport type IsAny<T> = 0 extends 1 & T ? true : false;\nexport type NotAny<T> = true extends IsAny<T> ? false : true;\n\nexport type Debug<T> = { [K in keyof T]: T[K] };\nexport type MergeInsertions<T> = T extends object\n  ? { [K in keyof T]: MergeInsertions<T[K]> }\n  : T;\n\nexport type Alike<X, Y> = Equal<MergeInsertions<X>, MergeInsertions<Y>>;\n\nexport type ExpectExtends<VALUE, EXPECTED> = EXPECTED extends VALUE\n  ? true\n  : false;\nexport type ExpectValidArgs<\n  FUNC extends (...args: any[]) => any,\n  ARGS extends any[],\n> = ARGS extends Parameters<FUNC> ? true : false;\n\nexport type UnionToIntersection<U> = (\n  U extends any ? (k: U) => void : never\n) extends (k: infer I) => void\n  ? I\n  : never;\n\nexport const doNotExecute = (func: () => any) => {};\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */\n    \"module\": \"commonjs\", /* Specify what module code is generated. */\n    \"noEmit\": true, /* Disable emitting files from a compilation. */\n    \"esModuleInterop\": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */\n    \"forceConsistentCasingInFileNames\": true, /* Ensure that casing is correct in imports. */\n    \"strict\": true, /* Enable all strict type-checking options. */\n  },\n  \"exclude\": [\n    \"dist\",\n    \"node_modules\"\n  ]\n}"
  },
  {
    "path": "turbo.json",
    "content": "{\n  \"$schema\": \"https://turbo.build/schema.json\",\n  \"pipeline\": {\n    \"build\": {\n      \"outputs\": [\"dist\"]\n    },\n    \"check-exports\": {\n      \"dependsOn\": [\"build\"]\n    },\n    \"lint\": {},\n    \"format-check\": {},\n    \"lint-pkg-json\": {},\n    \"publish\": {\n      \"dependsOn\": [\"build\", \"check-exports\", \"lint\", \"lint-pkg-json\"],\n      \"cache\": false\n    }\n  }\n}\n"
  }
]