{"_id":"@crescware/eslint-plugin-crescware-prefer-satisfies-over-annotation","_rev":"3-53692ed0f6a47d698479a8ef3b402bf7","name":"@crescware/eslint-plugin-crescware-prefer-satisfies-over-annotation","dist-tags":{"latest":"0.0.3"},"versions":{"0.0.1":{"name":"@crescware/eslint-plugin-crescware-prefer-satisfies-over-annotation","version":"0.0.1","_id":"@crescware/eslint-plugin-crescware-prefer-satisfies-over-annotation@0.0.1","maintainers":[{"name":"crescware","email":"okunokentaro+npm@crescware.com"}],"dist":{"shasum":"cf3bcbb768faf86d61c210bcb85832c629d7b266","tarball":"https://registry.npmjs.org/@crescware/eslint-plugin-crescware-prefer-satisfies-over-annotation/-/eslint-plugin-crescware-prefer-satisfies-over-annotation-0.0.1.tgz","fileCount":4,"integrity":"sha512-ONdnqW9IHKwKIXLhKiEeJ1dHzJUS6YzaPxvJI3P8iC9esJp3/QwmsgWsqfQ5b8zjLGbUTC7eO3uldU2OFDszSg==","signatures":[{"sig":"MEUCIA1/yjNtXs4XiT0DPYSEvwXTYD2pyKsr6GJYzzyWKclYAiEAqNyxLJ4Kip5AZRS+5Pd54WIQZXT5M8umgwQN6zbG7lc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":11363},"main":"dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":"./dist/index.js"},"gitHead":"72b3de85c7310eb8c2240c0251e2b89bab91e274","scripts":{"test":"vitest run","build":"rimraf dist && tsgo -p tsconfig.build.json","check":"pnpm run check:types && pnpm run check:lint && pnpm run check:knip && pnpm run test","format":"oxlint --fix && oxfmt","check:knip":"knip","check:lint":"oxlint && oxfmt --check","check:types":"tsgo -p tsconfig.json --noEmit","exec:fixtures":"oxlint -c fixtures/oxlintrc.default.json --no-ignore -f json fixtures/","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"crescware","email":"okunokentaro+npm@crescware.com"},"_npmVersion":"11.12.1","description":"An [oxlint](https://oxc.rs/docs/guide/usage/linter) JS plugin that prefers `satisfies` over a binding type annotation for object and array literals.","directories":{},"_nodeVersion":"24.15.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.33.2","devDependencies":{"knip":"6.7.0","oxfmt":"0.47.0","oxlint":"1.62.0","rimraf":"6.1.3","vitest":"4.1.5","@types/node":"24.12.2","@typescript/native-preview":"7.0.0-dev.20260422.1"},"_npmOperationalInternal":{"tmp":"tmp/eslint-plugin-crescware-prefer-satisfies-over-annotation_0.0.1_1781141669180_0.8891933864172001","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"@crescware/eslint-plugin-crescware-prefer-satisfies-over-annotation","version":"0.0.2","_id":"@crescware/eslint-plugin-crescware-prefer-satisfies-over-annotation@0.0.2","maintainers":[{"name":"crescware","email":"okunokentaro+npm@crescware.com"}],"dist":{"shasum":"3ccd82a4bce70514ea08699830d87494de010950","tarball":"https://registry.npmjs.org/@crescware/eslint-plugin-crescware-prefer-satisfies-over-annotation/-/eslint-plugin-crescware-prefer-satisfies-over-annotation-0.0.2.tgz","fileCount":4,"integrity":"sha512-e2SiAZrJjpAyhwULzmMlGKrd8T/volF36dFQkocMeYZYTgypVApRMviTK+dvOh0P/WOnnAZkE13qVo6d9JmjPg==","signatures":[{"sig":"MEYCIQDpGroAmEnLWoSmwNAHIra+PF8z5QaO4c4wjABxnU+qAgIhAIWZmgCttp+GQ83bugNUDrFdGadgmVSCcO4t/5AZIqR+","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":17786},"main":"dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":"./dist/index.js"},"gitHead":"3ce9943b13e7efaa307573ba4d239b7b4ca98ea3","scripts":{"test":"vitest run","build":"rimraf dist && tsgo -p tsconfig.build.json","check":"pnpm run check:types && pnpm run check:lint && pnpm run check:knip && pnpm run test","format":"oxlint --fix && oxfmt","check:knip":"knip","check:lint":"oxlint && oxfmt --check","check:types":"tsgo -p tsconfig.json --noEmit","exec:fixtures":"oxlint -c fixtures/oxlintrc.default.json --no-ignore -f json fixtures/","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"crescware","email":"okunokentaro+npm@crescware.com"},"_npmVersion":"11.12.1","description":"An [oxlint](https://oxc.rs/docs/guide/usage/linter) JS plugin that prefers `satisfies` over a binding type annotation or an `as` assertion for object and array literals.","directories":{},"_nodeVersion":"24.15.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.33.2","devDependencies":{"knip":"6.7.0","oxfmt":"0.47.0","oxlint":"1.62.0","rimraf":"6.1.3","vitest":"4.1.5","@types/node":"24.12.2","@typescript/native-preview":"7.0.0-dev.20260422.1"},"_npmOperationalInternal":{"tmp":"tmp/eslint-plugin-crescware-prefer-satisfies-over-annotation_0.0.2_1781158270207_0.6312347316029989","host":"s3://npm-registry-packages-npm-production"}},"0.0.3":{"name":"@crescware/eslint-plugin-crescware-prefer-satisfies-over-annotation","version":"0.0.3","type":"module","main":"dist/index.js","exports":{".":"./dist/index.js"},"publishConfig":{"access":"public"},"scripts":{"build":"rimraf dist && tsgo -p tsconfig.build.json","check":"pnpm run check:types && pnpm run check:lint && pnpm run check:knip && pnpm run test","check:knip":"knip","check:lint":"oxlint && oxfmt --check","check:types":"tsgo -p tsconfig.json --noEmit","exec:fixtures":"oxlint -c fixtures/oxlintrc.default.json --no-ignore -f json fixtures/","format":"oxlint --fix && oxfmt","prepublishOnly":"pnpm run build","test":"vitest run"},"devDependencies":{"@types/node":"24.12.2","@typescript/native-preview":"7.0.0-dev.20260422.1","knip":"6.7.0","oxfmt":"0.47.0","oxlint":"1.62.0","rimraf":"6.1.3","vitest":"4.1.5"},"packageManager":"pnpm@10.33.2","gitHead":"de4c7e2245fc5f2b392970cccf3d527d523a3fba","types":"./dist/index.d.ts","_id":"@crescware/eslint-plugin-crescware-prefer-satisfies-over-annotation@0.0.3","description":"An [oxlint](https://oxc.rs/docs/guide/usage/linter) JS plugin that prefers `satisfies` over a binding type annotation or an `as` assertion for object and array literals.","_nodeVersion":"24.15.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-c/x7p1DTswnVyfh8NpKBe6jb3iaIR3zJMB+1S3OByFXjNiuU/3Tf9DC2gNgpb3PgIsnpdQhvuPG794pbkfWCjw==","shasum":"6cd11d3d01d7ce59775768411aea3b242d83432a","tarball":"https://registry.npmjs.org/@crescware/eslint-plugin-crescware-prefer-satisfies-over-annotation/-/eslint-plugin-crescware-prefer-satisfies-over-annotation-0.0.3.tgz","fileCount":4,"unpackedSize":20482,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIC27tNfQNiX7kYTFusvt6S4NwPdJPDH+hR1SrSTuyJU/AiBHFsNUwv+rZwKJwC6QtQh+N83vGBYLnn8KhFNiNCbthA=="}]},"_npmUser":{"name":"crescware","email":"okunokentaro+npm@crescware.com"},"directories":{},"maintainers":[{"name":"crescware","email":"okunokentaro+npm@crescware.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/eslint-plugin-crescware-prefer-satisfies-over-annotation_0.0.3_1781857123726_0.6740453584382382"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-11T01:34:29.037Z","modified":"2026-06-19T08:18:43.984Z","0.0.1":"2026-06-11T01:34:29.344Z","0.0.2":"2026-06-11T06:11:10.350Z","0.0.3":"2026-06-19T08:18:43.888Z"},"description":"An [oxlint](https://oxc.rs/docs/guide/usage/linter) JS plugin that prefers `satisfies` over a binding type annotation or an `as` assertion for object and array literals.","maintainers":[{"name":"crescware","email":"okunokentaro+npm@crescware.com"}],"readme":"# @crescware/eslint-plugin-crescware-prefer-satisfies-over-annotation\n\nAn [oxlint](https://oxc.rs/docs/guide/usage/linter) JS plugin that prefers `satisfies` over a binding type annotation or an `as` assertion for object and array literals.\n\n## Rule: `prefer-satisfies-over-annotation`\n\nA `const` whose initializer is a plain object or array literal should declare its type with `satisfies`, not with a binding annotation or an `as` assertion. `satisfies` keeps excess-property checking strict while preserving the literal's narrow inferred type, instead of widening it (an annotation) or overriding it (an `as` assertion).\n\n```ts\n// NG: a type annotation on the literal (always reported)\nconst obj: Something = { ... };\nconst arr: Something[] = [ ... ];\n\n// NG: a literal with no declared type (reported unless `allowWithoutAnnotation` is enabled)\nconst obj = { ... };\nconst arr = [ ... ];\n\n// NG: an `as` assertion on the literal (reported unless `allowAsAssertion` is enabled)\nconst obj = { ... } as Something;\nconst arr = [ ... ] as Something[];\n\n// NG: `as const` declares no type to check against (reported unless `allowAsConst` is enabled)\nconst frozen = { ... } as const;\n\n// OK\nconst obj = { ... } satisfies Something;\nconst arr = [ ... ] satisfies Something[];\n// keep the freeze of `as const` and add a check -- `as const` comes first:\nconst frozen = { ... } as const satisfies Something;\n\n// OK: empty literals are allowed by default -- `satisfies` cannot type them\n// (`[] satisfies T` still infers `never[]`). See `allowEmptyLiteral`.\nconst empty = {};\nconst emptyArr = [];\n```\n\n### Scope\n\nThe rule fires when a `const` initializer is a plain object or array literal (`ObjectExpression` / `ArrayExpression`), or such a literal wrapped in an `as` assertion. Object and array literals are treated the same.\n\n- With a type annotation (`const x: T = {...}`): always reported.\n- Without a type annotation (`const x = {...}`): reported by default, ignored when `allowWithoutAnnotation` is `true`.\n- With an `as` assertion other than `as const` (`const x = {...} as T`, including chains such as `{...} as unknown as T`): reported by default, ignored when `allowAsAssertion` is `true`.\n- With an `as const` assertion (`const x = {...} as const`): reported by default, ignored when `allowAsConst` is `true`. `as const` freezes the literal but declares no type to check against; to keep the freeze and add a check, write `{...} as const satisfies T` (the `as const` must come before `satisfies` -- `{...} satisfies T as const` is a type error because `as const` can only apply to a literal).\n- An empty literal (`const x = {}` / `const x = []`, with zero properties/elements): allowed by default, because `satisfies` cannot type it usefully (`[] satisfies T` still infers `never[]`). Controlled by `allowEmptyLiteral`, which takes precedence over `allowAsConst` (so `{} as const` follows the `allowEmptyLiteral` policy). A spread (`[...xs]` / `{...o}`) counts as non-empty and stays in scope.\n- Out of scope: a `satisfies` clause (`const x = {...} satisfies T`), and initializers that are not object/array literals (`const v = JSON.parse(...)`, `const n: number = 1`).\n- Out of scope: `let` / `var` declarations.\n\nThe rule does not autofix; it reports only.\n\n### Options\n\n```jsonc\n\"crescware-prefer-satisfies-over-annotation/prefer-satisfies-over-annotation\": [\n  \"error\",\n  {\n    // false (default): a literal with no type annotation is reported.\n    // true: annotationless literals pass (annotated / `as` literals are unaffected).\n    \"allowWithoutAnnotation\": false,\n\n    // false (default): an `as` assertion other than `as const` is reported.\n    // true: `as` assertions on literals pass.\n    \"allowAsAssertion\": false,\n\n    // false (default): a bare `as const` on a literal is reported.\n    // true: `as const` on literals passes. (To keep the freeze and a check,\n    //       write `{...} as const satisfies T`.)\n    \"allowAsConst\": false,\n\n    // true (default): empty `{}` / `[]` literals are not reported.\n    // false: report them with the standard message.\n    // { \"message\": \"...\" }: report them with that custom message.\n    \"allowEmptyLiteral\": true\n  }\n]\n```\n\n| Option                   | Type                             | Default | Effect                                                                                                                                                                 |\n| ------------------------ | -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `allowWithoutAnnotation` | `boolean`                        | `false` | When `true`, suppresses reports for literals that have no type annotation. Annotated and `as`-asserted literals are still reported.                                    |\n| `allowAsAssertion`       | `boolean`                        | `false` | When `true`, suppresses reports for `as` assertions (other than `as const`) on literals.                                                                               |\n| `allowAsConst`           | `boolean`                        | `false` | When `true`, suppresses reports for a bare `as const` on a literal. To keep the freeze while declaring a type, write `{...} as const satisfies T` (`as const` first).  |\n| `allowEmptyLiteral`      | `boolean \\| { message: string }` | `true`  | An empty `{}` / `[]` cannot be typed by `satisfies`. `true` skips it; `false` reports it with the standard message; `{ message }` reports it with that custom message. |\n\n## Usage\n\nRegister the plugin in your `.oxlintrc.json` and enable the rule:\n\n```json\n{\n  \"jsPlugins\": [\n    \"@crescware/eslint-plugin-crescware-prefer-satisfies-over-annotation\"\n  ],\n  \"rules\": {\n    \"crescware-prefer-satisfies-over-annotation/prefer-satisfies-over-annotation\": \"error\"\n  }\n}\n```\n\n## Stack\n\n- **Runtime**: Node.js 24 (via [mise](https://mise.jdx.dev/))\n- **Package manager**: pnpm (via corepack)\n- **Language**: TypeScript ([native preview](https://github.com/microsoft/typescript-go))\n- **Test**: [Vitest](https://vitest.dev/)\n- **Lint**: [oxlint](https://oxc.rs/docs/guide/usage/linter)\n- **Format**: [oxfmt](https://github.com/oxc-project/oxc)\n- **Unused code**: [Knip](https://knip.dev/)\n\n## Setup\n\n```sh\nmise install\ncorepack enable\npnpm install\n```\n\n## Scripts\n\n| Command            | Description                              |\n| ------------------ | ---------------------------------------- |\n| `pnpm build`       | Compile `src` to `dist`                  |\n| `pnpm check`       | Run all checks (types, lint, knip, test) |\n| `pnpm check:types` | Type check                               |\n| `pnpm check:lint`  | Lint and format check                    |\n| `pnpm check:knip`  | Unused files/exports check               |\n| `pnpm test`        | Run fixture integration tests            |\n| `pnpm format`      | Fix lint and format                      |\n","readmeFilename":"README.md"}