From dd969477e8cb10a4402eccc051a1d1206853e3b0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 22:43:04 -0700 Subject: [PATCH 1/3] chore(deps): update dependency cspell to v9.4.0 (#11831) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 355 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 182 insertions(+), 173 deletions(-) diff --git a/yarn.lock b/yarn.lock index 275b03e3429..eff9f91cd8b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1587,21 +1587,21 @@ __metadata: languageName: node linkType: hard -"@cspell/cspell-bundled-dicts@npm:9.3.1": - version: 9.3.1 - resolution: "@cspell/cspell-bundled-dicts@npm:9.3.1" +"@cspell/cspell-bundled-dicts@npm:9.4.0": + version: 9.4.0 + resolution: "@cspell/cspell-bundled-dicts@npm:9.4.0" dependencies: "@cspell/dict-ada": ^4.1.1 "@cspell/dict-al": ^1.1.1 - "@cspell/dict-aws": ^4.0.15 + "@cspell/dict-aws": ^4.0.16 "@cspell/dict-bash": ^4.2.2 "@cspell/dict-companies": ^3.2.7 - "@cspell/dict-cpp": ^6.0.14 + "@cspell/dict-cpp": ^6.0.15 "@cspell/dict-cryptocurrencies": ^5.0.5 "@cspell/dict-csharp": ^4.0.7 "@cspell/dict-css": ^4.0.18 "@cspell/dict-dart": ^2.3.1 - "@cspell/dict-data-science": ^2.0.11 + "@cspell/dict-data-science": ^2.0.12 "@cspell/dict-django": ^4.1.5 "@cspell/dict-docker": ^1.1.16 "@cspell/dict-dotnet": ^5.0.10 @@ -1619,7 +1619,7 @@ __metadata: "@cspell/dict-golang": ^6.0.24 "@cspell/dict-google": ^1.0.9 "@cspell/dict-haskell": ^4.0.6 - "@cspell/dict-html": ^4.0.12 + "@cspell/dict-html": ^4.0.13 "@cspell/dict-html-symbol-entities": ^4.0.4 "@cspell/dict-java": ^5.0.12 "@cspell/dict-julia": ^1.1.1 @@ -1629,66 +1629,67 @@ __metadata: "@cspell/dict-lorem-ipsum": ^4.0.5 "@cspell/dict-lua": ^4.0.8 "@cspell/dict-makefile": ^1.0.5 - "@cspell/dict-markdown": ^2.0.12 + "@cspell/dict-markdown": ^2.0.13 "@cspell/dict-monkeyc": ^1.0.11 "@cspell/dict-node": ^5.0.8 - "@cspell/dict-npm": ^5.2.20 + "@cspell/dict-npm": ^5.2.25 "@cspell/dict-php": ^4.1.0 "@cspell/dict-powershell": ^5.0.15 "@cspell/dict-public-licenses": ^2.0.15 - "@cspell/dict-python": ^4.2.21 + "@cspell/dict-python": ^4.2.23 "@cspell/dict-r": ^2.1.1 "@cspell/dict-ruby": ^5.0.9 "@cspell/dict-rust": ^4.0.12 "@cspell/dict-scala": ^5.0.8 "@cspell/dict-shell": ^1.1.2 - "@cspell/dict-software-terms": ^5.1.11 + "@cspell/dict-software-terms": ^5.1.15 "@cspell/dict-sql": ^2.2.1 "@cspell/dict-svelte": ^1.0.7 "@cspell/dict-swift": ^2.0.6 "@cspell/dict-terraform": ^1.1.3 "@cspell/dict-typescript": ^3.2.3 "@cspell/dict-vue": ^3.0.5 - checksum: 7c0d4a4cc62c405394a9778fc4c405856f169841e595dc3ba1ad17a7bc72612619246146773a10be3be7eb13682088e8b03a50bf89c12fbdbdcb5fa48b0f9bea + "@cspell/dict-zig": ^1.0.0 + checksum: 468057098fcc90a49e52c472e816299671e22fc273046ea6341a048a1f8333b81dc219bd5dabde66240c7f53868540683b58f1462b1d9aa11e74b321f4534faf languageName: node linkType: hard -"@cspell/cspell-json-reporter@npm:9.3.1": - version: 9.3.1 - resolution: "@cspell/cspell-json-reporter@npm:9.3.1" +"@cspell/cspell-json-reporter@npm:9.4.0": + version: 9.4.0 + resolution: "@cspell/cspell-json-reporter@npm:9.4.0" dependencies: - "@cspell/cspell-types": 9.3.1 - checksum: 7452345aad8512d5e90901b12e5fd67bbe141c0c0f8e395911f138c8fa7ab47d47f48394160156de03ca54882cab5caf16c18b85df25ad685751211bb5b665ab + "@cspell/cspell-types": 9.4.0 + checksum: 41c8df1aa02cc87b2bc74d1290bff6bd7290960647c13228756c7e0827b52a0497bb7f2a5c8f0dd49dbefe3b9c46251e24b7c27a0d5df929fcc212133817cd01 languageName: node linkType: hard -"@cspell/cspell-pipe@npm:9.3.1": - version: 9.3.1 - resolution: "@cspell/cspell-pipe@npm:9.3.1" - checksum: d20df305a67f738e4a6f35774a419f2048b2bb1d0e9f8870d3fb99bdf8134e4198c71b0f7d82603098f32e202e7da53af280abfa0b2a988a3515d57bb648af4c +"@cspell/cspell-pipe@npm:9.4.0": + version: 9.4.0 + resolution: "@cspell/cspell-pipe@npm:9.4.0" + checksum: aa08638ed53e3a9266dbd112e7ec5b566fd5ef98b53696d0d2a67083fbe8c2a5fc9cfad19a84c8a41639c450f43f6ad388bb4fa09ee1dfb0796a6b34a0b7cfc3 languageName: node linkType: hard -"@cspell/cspell-resolver@npm:9.3.1": - version: 9.3.1 - resolution: "@cspell/cspell-resolver@npm:9.3.1" +"@cspell/cspell-resolver@npm:9.4.0": + version: 9.4.0 + resolution: "@cspell/cspell-resolver@npm:9.4.0" dependencies: global-directory: ^4.0.1 - checksum: 10d3bb2e391d8b2cef70942058c0a1b8a84c15211141c943a6d3b37e543ab08538e2493b920bbc66c294602d08222803dcee13a703faf73539f4e11210880964 + checksum: b1e355579411eaf38285b35905f007d80f8ade4482b3db632b933b995428bccf032e8afbfae86fe9ec342915470951e4900f07c3e187a0a0d1950bdf3340b6a9 languageName: node linkType: hard -"@cspell/cspell-service-bus@npm:9.3.1": - version: 9.3.1 - resolution: "@cspell/cspell-service-bus@npm:9.3.1" - checksum: 2c06e15b4801bec9d7dad6330cd68ac1bc909fe225cd0fda3be785386b7fbdf9aa4641c9e6fadc5beb99b476cd7a0dd087005e69106f1cd3569d9b812986b2ff +"@cspell/cspell-service-bus@npm:9.4.0": + version: 9.4.0 + resolution: "@cspell/cspell-service-bus@npm:9.4.0" + checksum: 5c473bdcc6642df89977784bcbee891563a3aae47997c01806e56395ec94636782c0fe7e09f6046177561758fbe72fb83036111eabf350492a6b53857a14e679 languageName: node linkType: hard -"@cspell/cspell-types@npm:9.3.1": - version: 9.3.1 - resolution: "@cspell/cspell-types@npm:9.3.1" - checksum: 3e7906eb8899773dfd4d027b6e68de75ece31831dd5608eb9ce308cf086a2aeb454e0249fdbe6e22c5963041f1027acd9895bd9838ea90d99ea33c386a5c202b +"@cspell/cspell-types@npm:9.4.0": + version: 9.4.0 + resolution: "@cspell/cspell-types@npm:9.4.0" + checksum: 56b386963c64740883281e4091c1e147115f5e52c0b14c949a95f4c5c1216b8bc8526f8147b239eaf611e0dd2641877bec6146be784af4bb849db5e14f7cd68f languageName: node linkType: hard @@ -1706,10 +1707,10 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-aws@npm:^4.0.15": - version: 4.0.15 - resolution: "@cspell/dict-aws@npm:4.0.15" - checksum: 7a865cbc3ed31b22623c343483df47e9874bc238497405aae6e8c7975355b1ee57b0d2616706d1cb335c1037a72a6bb3a8d020edea9157035675101f547b1ff8 +"@cspell/dict-aws@npm:^4.0.16": + version: 4.0.16 + resolution: "@cspell/dict-aws@npm:4.0.16" + checksum: 51013c417a10ffc3cdc74debd7197bce80f204a03afbbfcb567ec9e9afd6b81ddffd275d18f3c007218090409024839ee1f6c54178149b70170879ca0f4d6b61 languageName: node linkType: hard @@ -1729,10 +1730,10 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-cpp@npm:^6.0.14": - version: 6.0.14 - resolution: "@cspell/dict-cpp@npm:6.0.14" - checksum: be71603fb55e4d4db12417fbf96ba60e613888bdfe5bab303cddf555b019d453e54b8c4388566d1eeb671233051fc3f977e79b1c9c621cd4010c0cf778aad973 +"@cspell/dict-cpp@npm:^6.0.15": + version: 6.0.15 + resolution: "@cspell/dict-cpp@npm:6.0.15" + checksum: 9c76cd6e5533837fcd4043ce298205f66cbd1994b8040813ce5bfa6da5500c9426cca9155c161ee068fd0b1f9733055b32a7f373b6d8805f883ab77342d45b41 languageName: node linkType: hard @@ -1764,10 +1765,10 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-data-science@npm:^2.0.11": - version: 2.0.11 - resolution: "@cspell/dict-data-science@npm:2.0.11" - checksum: 2efebe09848e259419f6005485a1b6e627881292b5fab5ae5a72a7c38474d44945d78de8b16b029b798428f58923266a3da5566ca292790b9851d2b39e645a72 +"@cspell/dict-data-science@npm:^2.0.12": + version: 2.0.12 + resolution: "@cspell/dict-data-science@npm:2.0.12" + checksum: c0983785482a7ad6be103b138ad08c125dd44fe385233bb8e010dd76a0a3295458da17c3e88307dc3a27dfd5bbd478f62f46b8de72da66fbdbc1106b0968671e languageName: node linkType: hard @@ -1897,10 +1898,10 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-html@npm:^4.0.12": - version: 4.0.12 - resolution: "@cspell/dict-html@npm:4.0.12" - checksum: 5441fa727bf6fc49039c9051d40b8fe4c05712f5a21cfa267affb0537f02400ffd23dff12a4bff69702996d1038c331f13a2071ebcf1235b1a5679ae2c527d0b +"@cspell/dict-html@npm:^4.0.13": + version: 4.0.13 + resolution: "@cspell/dict-html@npm:4.0.13" + checksum: 1cfd59775d8956b12e86ed49a5c6f69e89b8bbd8c188d1ade973668f97997987855ae9d838a969e5b38d2885869bbd54c620d5290a1b93c5b723ed8d9deb4c04 languageName: node linkType: hard @@ -1960,15 +1961,15 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-markdown@npm:^2.0.12": - version: 2.0.12 - resolution: "@cspell/dict-markdown@npm:2.0.12" +"@cspell/dict-markdown@npm:^2.0.13": + version: 2.0.13 + resolution: "@cspell/dict-markdown@npm:2.0.13" peerDependencies: "@cspell/dict-css": ^4.0.18 - "@cspell/dict-html": ^4.0.12 + "@cspell/dict-html": ^4.0.13 "@cspell/dict-html-symbol-entities": ^4.0.4 "@cspell/dict-typescript": ^3.2.3 - checksum: 20f9510b808a2b394ebae83257569c76ce23883f3902e32ffea5ef83d645052b7fba500e2c4ab96e669c93c250158327330a34453657bf2b6162e9d303148c44 + checksum: 7f1d131301ff7128b974ab35498fe2842584626c2c8f45a11a30fc245439417caaa7a615611ce324f834648da3593fd5c305999af157d317973c2f2c0a2a8849 languageName: node linkType: hard @@ -1986,10 +1987,10 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-npm@npm:^5.2.20": - version: 5.2.20 - resolution: "@cspell/dict-npm@npm:5.2.20" - checksum: 2d386aa3686c796726ab20726f6296c85dff6140b30a32523c70d5b9b18be959a72efd65f0be84aab4b446691392185dc149aa1bc836b793f88258c6c7d248aa +"@cspell/dict-npm@npm:^5.2.25": + version: 5.2.25 + resolution: "@cspell/dict-npm@npm:5.2.25" + checksum: 64b64e5aa84b21e8a84a21d1e1e6e87548ee159e819dcd72b211b14bc0e78a2563ce6488ddbcff84327533223a58c40782da3d3d3ab97ce956872a8db6973589 languageName: node linkType: hard @@ -2014,12 +2015,12 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-python@npm:^4.2.21": - version: 4.2.21 - resolution: "@cspell/dict-python@npm:4.2.21" +"@cspell/dict-python@npm:^4.2.23": + version: 4.2.23 + resolution: "@cspell/dict-python@npm:4.2.23" dependencies: - "@cspell/dict-data-science": ^2.0.11 - checksum: 92b689de5c965a737867e8a19537cef677792bfae40baf77c55544f49fe86c7890d4272f06454f737ad3b769b1d7951e30b9dba3a0d5b1415c92607b940a15e9 + "@cspell/dict-data-science": ^2.0.12 + checksum: 96ae152c472edcba636903a3d166ac1b1d6ece7d4100882f37a2bdc0ef139df2306ee17f10962fc41adaeedc5b130e77167d5dd75e5d364b04c3399395f11098 languageName: node linkType: hard @@ -2058,10 +2059,10 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-software-terms@npm:^5.1.11": - version: 5.1.11 - resolution: "@cspell/dict-software-terms@npm:5.1.11" - checksum: f24cc0a6149237d8f4f9f6841ed9ae1c228c675429f5edd1d3324e87396058f07de9dae9f281654075c1dfc4ba6647956826cd544808fa7d7c6b86d1abd91fab +"@cspell/dict-software-terms@npm:^5.1.15": + version: 5.1.15 + resolution: "@cspell/dict-software-terms@npm:5.1.15" + checksum: 68274f6ace50ad72e3883c6efd3d8508a0da55e24431e9710b71e9d9eb87805b8ec18a7e093369b2ba49efb15e2e7389cc6c423dc5e72bf97685716d46232265 languageName: node linkType: hard @@ -2107,34 +2108,41 @@ __metadata: languageName: node linkType: hard -"@cspell/dynamic-import@npm:9.3.1": - version: 9.3.1 - resolution: "@cspell/dynamic-import@npm:9.3.1" +"@cspell/dict-zig@npm:^1.0.0": + version: 1.0.0 + resolution: "@cspell/dict-zig@npm:1.0.0" + checksum: 85a40bf4398ba6d6f27dbfc57a9c5e176f18e60c22b97b09b90a813165b98c6d2ac0d096e1e7670af8dee7a30cdd93804ef7ab8b7d05d4ce30a0d3def13b1c1c + languageName: node + linkType: hard + +"@cspell/dynamic-import@npm:9.4.0": + version: 9.4.0 + resolution: "@cspell/dynamic-import@npm:9.4.0" dependencies: - "@cspell/url": 9.3.1 + "@cspell/url": 9.4.0 import-meta-resolve: ^4.2.0 - checksum: dcba8075c8a5ad7cbf9ecae5f4475268cb2685f7c9691c721417e44c584fe2ed177d9f4c19993ec06fc3753f2e1481c04a541ca6f0e9410c8ed47f7089a8d922 + checksum: e564ac14e4c56e0f2b7c760ab89b0bb99e8a73b79c7e451cb9440cc86a3241ca33d83e7402787b131749e3f5472fb350219ab28387131834aec45f796079fc45 languageName: node linkType: hard -"@cspell/filetypes@npm:9.3.1": - version: 9.3.1 - resolution: "@cspell/filetypes@npm:9.3.1" - checksum: c61662bdeda0fd99efe9518189f812a95fa79aa1766cfdebab7a763173669968552b8861063bacb30d1a0ccdf5c54adf70dcc80604194eef0f2d45757961ba95 +"@cspell/filetypes@npm:9.4.0": + version: 9.4.0 + resolution: "@cspell/filetypes@npm:9.4.0" + checksum: 6054f7c1279d66059b8dcb791d729d8694536dbbfb8870f14a21a2821eff31882dc8f5664e22940c89968118c0eca1a781a934315e2ddac0aacf412be7643af0 languageName: node linkType: hard -"@cspell/strong-weak-map@npm:9.3.1": - version: 9.3.1 - resolution: "@cspell/strong-weak-map@npm:9.3.1" - checksum: 1df8a8c9b80a48edc49916263e56bd05403af7a82a4ef389ab3e6db0d37dfb1bbe88076abf93928a5674ab01c3abea15ea4c0100eb9a032fd40d47d1e46c53ad +"@cspell/strong-weak-map@npm:9.4.0": + version: 9.4.0 + resolution: "@cspell/strong-weak-map@npm:9.4.0" + checksum: 8d5ff5dc12f3d7259d51575cada0231a9ee936b01d50e32ccc838ac451a5223f300a9c692c65dd0997212ef92c4a78aac768264e891e4c99914d921a4caba672 languageName: node linkType: hard -"@cspell/url@npm:9.3.1": - version: 9.3.1 - resolution: "@cspell/url@npm:9.3.1" - checksum: bb5b9ecb9d211772615e4699636d3bdec95778d50be94f9505f8ed06bd1a1e8a21ee3852b2cfaf52cac6fa464965b34142b42dfc4dc6c78265da2cd94322cb57 +"@cspell/url@npm:9.4.0": + version: 9.4.0 + resolution: "@cspell/url@npm:9.4.0" + checksum: 700f0f4919736f722d2654b151e60327037aca75d15fc30ebe1ee2a165040231001f78a38fe30e2813a833cd2b721181e46da217b4e697c6c88b44eb170715be languageName: node linkType: hard @@ -7168,10 +7176,10 @@ __metadata: languageName: node linkType: hard -"ansi-regex@npm:^6.0.1": - version: 6.0.1 - resolution: "ansi-regex@npm:6.0.1" - checksum: 1ff8b7667cded1de4fa2c9ae283e979fc87036864317da86a2e546725f96406746411d0d85e87a2d12fa5abd715d90006de7fa4fa0477c92321ad3b4c7d4e169 +"ansi-regex@npm:^6.0.1, ansi-regex@npm:^6.2.2": + version: 6.2.2 + resolution: "ansi-regex@npm:6.2.2" + checksum: 9b17ce2c6daecc75bcd5966b9ad672c23b184dc3ed9bf3c98a0702f0d2f736c15c10d461913568f2cf527a5e64291c7473358885dd493305c84a1cfed66ba94f languageName: node linkType: hard @@ -8771,94 +8779,94 @@ __metadata: languageName: node linkType: hard -"cspell-config-lib@npm:9.3.1": - version: 9.3.1 - resolution: "cspell-config-lib@npm:9.3.1" +"cspell-config-lib@npm:9.4.0": + version: 9.4.0 + resolution: "cspell-config-lib@npm:9.4.0" dependencies: - "@cspell/cspell-types": 9.3.1 + "@cspell/cspell-types": 9.4.0 comment-json: ^4.4.1 - smol-toml: ^1.4.2 - yaml: ^2.8.1 - checksum: 0f5969764bff138a0c9fd19d24a9e05e39427662dc5b8e70685a99defc3623b48fe0c1a8b55e28221c1b954424fcae57275975731cadca713995c4424ac5b680 + smol-toml: ^1.5.2 + yaml: ^2.8.2 + checksum: 4562cf52e9996dbc68b068d9f20038db0c46fb15c4db2feb4bec02276fc7b8579a0e7af417cfb3f1fa9b481d47a19e7ecf3f8b5db021825d607e536b1d75d094 languageName: node linkType: hard -"cspell-dictionary@npm:9.3.1": - version: 9.3.1 - resolution: "cspell-dictionary@npm:9.3.1" +"cspell-dictionary@npm:9.4.0": + version: 9.4.0 + resolution: "cspell-dictionary@npm:9.4.0" dependencies: - "@cspell/cspell-pipe": 9.3.1 - "@cspell/cspell-types": 9.3.1 - cspell-trie-lib: 9.3.1 - fast-equals: ^5.3.2 - checksum: fee04e844dd287d80748990027f60b59f460f4854fbb497ea59e9f0cfb64836c3fe274f4fc57d6ba7cf7108e4ff8a8a33740c841d145bb0d220d80868932a943 + "@cspell/cspell-pipe": 9.4.0 + "@cspell/cspell-types": 9.4.0 + cspell-trie-lib: 9.4.0 + fast-equals: ^5.3.3 + checksum: a627a821bafd08d8deda44ad33aae363a06b6395e99addec86a95fc0e9b2d00a32e748ec8b329994ade8c49ae05c4deefc168007690246e6cc3eeda941ef518b languageName: node linkType: hard -"cspell-gitignore@npm:9.3.1": - version: 9.3.1 - resolution: "cspell-gitignore@npm:9.3.1" +"cspell-gitignore@npm:9.4.0": + version: 9.4.0 + resolution: "cspell-gitignore@npm:9.4.0" dependencies: - "@cspell/url": 9.3.1 - cspell-glob: 9.3.1 - cspell-io: 9.3.1 + "@cspell/url": 9.4.0 + cspell-glob: 9.4.0 + cspell-io: 9.4.0 bin: cspell-gitignore: bin.mjs - checksum: 4416034bc854cbfdadb7abd635a7405285ec610a5b4904529f60507d21bb3bb013b9bc29e58ff1ef4a772187b742c550dd9781627f42031291a8b4f1f326d6d0 + checksum: ac495c8985ef4792f2cbc898ff3a0651f26c96a9238dafb232172551859ca8238987ae93c94d7b7f44145fa8d86799bedd9cbec1c2fecc246e8242371e2ca3c9 languageName: node linkType: hard -"cspell-glob@npm:9.3.1": - version: 9.3.1 - resolution: "cspell-glob@npm:9.3.1" +"cspell-glob@npm:9.4.0": + version: 9.4.0 + resolution: "cspell-glob@npm:9.4.0" dependencies: - "@cspell/url": 9.3.1 + "@cspell/url": 9.4.0 picomatch: ^4.0.3 - checksum: 1feaf198b6680b0b8a58e8ae65063cd72d42774f86c6cff905950df52d6474cf50b5c984655b18b60f9ff4693369b9e195bf2b53c3479d337496b2c9433d5649 + checksum: ee7511179bfb9695a2355d6d24d8956f2db6b68942c965d2bc73a7aaa248424820d6777b76dd2bfcab06e96ea682475d2fa16622322ecb4478403215c2a1a207 languageName: node linkType: hard -"cspell-grammar@npm:9.3.1": - version: 9.3.1 - resolution: "cspell-grammar@npm:9.3.1" +"cspell-grammar@npm:9.4.0": + version: 9.4.0 + resolution: "cspell-grammar@npm:9.4.0" dependencies: - "@cspell/cspell-pipe": 9.3.1 - "@cspell/cspell-types": 9.3.1 + "@cspell/cspell-pipe": 9.4.0 + "@cspell/cspell-types": 9.4.0 bin: cspell-grammar: bin.mjs - checksum: 1ec40070f972fe634acfec4b84a4b666b92f311ac66ca9ca060eb3f9254e78e03ba33c1b150f77b6555511d5956854f662cebcaf1c1dc24c784d4597e4d10a7d + checksum: 38906ce6ae9a448fe1e3207652dce1f902addfee942116fb720def35e9596524407d6370e1a945e4c02f1ff4c7633955b1bd533ebaef2f826e4c82593b0b9c5a languageName: node linkType: hard -"cspell-io@npm:9.3.1": - version: 9.3.1 - resolution: "cspell-io@npm:9.3.1" +"cspell-io@npm:9.4.0": + version: 9.4.0 + resolution: "cspell-io@npm:9.4.0" dependencies: - "@cspell/cspell-service-bus": 9.3.1 - "@cspell/url": 9.3.1 - checksum: fe5cf7b7e89a324813f83a611947830ee1ce8cabfe501c63252a43963f5c352d23f2089d7df8ce15b66bb4f74d33931e5795a387e8ecb0043cff5d0e6f092b72 + "@cspell/cspell-service-bus": 9.4.0 + "@cspell/url": 9.4.0 + checksum: 242947ab711dbd2dbd97d6f8d2932e92a09365fbd6002c7a890a1d08ed0a9be68a08c60bbcb67948f1e7d47de82b1631ffed3fa7171661744efb65af31fd10e8 languageName: node linkType: hard -"cspell-lib@npm:9.3.1": - version: 9.3.1 - resolution: "cspell-lib@npm:9.3.1" - dependencies: - "@cspell/cspell-bundled-dicts": 9.3.1 - "@cspell/cspell-pipe": 9.3.1 - "@cspell/cspell-resolver": 9.3.1 - "@cspell/cspell-types": 9.3.1 - "@cspell/dynamic-import": 9.3.1 - "@cspell/filetypes": 9.3.1 - "@cspell/strong-weak-map": 9.3.1 - "@cspell/url": 9.3.1 +"cspell-lib@npm:9.4.0": + version: 9.4.0 + resolution: "cspell-lib@npm:9.4.0" + dependencies: + "@cspell/cspell-bundled-dicts": 9.4.0 + "@cspell/cspell-pipe": 9.4.0 + "@cspell/cspell-resolver": 9.4.0 + "@cspell/cspell-types": 9.4.0 + "@cspell/dynamic-import": 9.4.0 + "@cspell/filetypes": 9.4.0 + "@cspell/strong-weak-map": 9.4.0 + "@cspell/url": 9.4.0 clear-module: ^4.1.2 - cspell-config-lib: 9.3.1 - cspell-dictionary: 9.3.1 - cspell-glob: 9.3.1 - cspell-grammar: 9.3.1 - cspell-io: 9.3.1 - cspell-trie-lib: 9.3.1 + cspell-config-lib: 9.4.0 + cspell-dictionary: 9.4.0 + cspell-glob: 9.4.0 + cspell-grammar: 9.4.0 + cspell-io: 9.4.0 + cspell-trie-lib: 9.4.0 env-paths: ^3.0.0 gensequence: ^8.0.8 import-fresh: ^3.3.1 @@ -8866,39 +8874,40 @@ __metadata: vscode-languageserver-textdocument: ^1.0.12 vscode-uri: ^3.1.0 xdg-basedir: ^5.1.0 - checksum: 65319dbd5e78305a51b0adf4122b99866516fc30ff8134f45def3c445627fc48e6b0945668dca735d05fba531b2e09ba0c90b94a6dae92750576ae0e5a5ae092 + checksum: e6aca50548582022bec9c09ac936e58ca4dcc1b445496432cfce2b3fab1d173eaf7733adb041a63b2950da0aa84d0c14474e788f5209c9270d247e41059dd065 languageName: node linkType: hard -"cspell-trie-lib@npm:9.3.1": - version: 9.3.1 - resolution: "cspell-trie-lib@npm:9.3.1" +"cspell-trie-lib@npm:9.4.0": + version: 9.4.0 + resolution: "cspell-trie-lib@npm:9.4.0" dependencies: - "@cspell/cspell-pipe": 9.3.1 - "@cspell/cspell-types": 9.3.1 + "@cspell/cspell-pipe": 9.4.0 + "@cspell/cspell-types": 9.4.0 gensequence: ^8.0.8 - checksum: 4fa4ed8cdb7245794d3299cab5e2ec541e55efe84e10aef876f67c3eba7f8bba037c690b5345e17d46e21c4b89f0fa57ac8ee43278d5961fa790bb56250a8842 + checksum: 4a3e00c836701d3fb9268ac6479e45d8799b0629539001c2e3583344a76402eecb3e4592c2e63c768c78de485247a4e1eb0357d2a02edb9846a35214edca3d16 languageName: node linkType: hard "cspell@npm:^9.0.0": - version: 9.3.1 - resolution: "cspell@npm:9.3.1" - dependencies: - "@cspell/cspell-json-reporter": 9.3.1 - "@cspell/cspell-pipe": 9.3.1 - "@cspell/cspell-types": 9.3.1 - "@cspell/dynamic-import": 9.3.1 - "@cspell/url": 9.3.1 + version: 9.4.0 + resolution: "cspell@npm:9.4.0" + dependencies: + "@cspell/cspell-json-reporter": 9.4.0 + "@cspell/cspell-pipe": 9.4.0 + "@cspell/cspell-types": 9.4.0 + "@cspell/dynamic-import": 9.4.0 + "@cspell/url": 9.4.0 + ansi-regex: ^6.2.2 chalk: ^5.6.2 chalk-template: ^1.1.2 commander: ^14.0.2 - cspell-config-lib: 9.3.1 - cspell-dictionary: 9.3.1 - cspell-gitignore: 9.3.1 - cspell-glob: 9.3.1 - cspell-io: 9.3.1 - cspell-lib: 9.3.1 + cspell-config-lib: 9.4.0 + cspell-dictionary: 9.4.0 + cspell-gitignore: 9.4.0 + cspell-glob: 9.4.0 + cspell-io: 9.4.0 + cspell-lib: 9.4.0 fast-json-stable-stringify: ^2.1.0 flatted: ^3.3.3 semver: ^7.7.3 @@ -8906,7 +8915,7 @@ __metadata: bin: cspell: bin.mjs cspell-esm: bin.mjs - checksum: f24dbcfd66bcd3d09d95c0db9fdd94d0f9d27911d583053dc9fa1f06454d88c790e52d1865f7cf6f8e6873e773fed23cf680942b78b18ca4fd90a2ace3da5703 + checksum: b7b736ed8f8db80f489a4f8b8f9ea7c179f3d7b07d4512976a05807e9f422f544e86a91f6819a80f8b9d0e43918361392b012774c2d24506bae785759a58d3fc languageName: node linkType: hard @@ -10900,7 +10909,7 @@ __metadata: languageName: node linkType: hard -"fast-equals@npm:^5.3.2": +"fast-equals@npm:^5.3.3": version: 5.3.3 resolution: "fast-equals@npm:5.3.3" checksum: 52f9e48d12185abe112d54653b8a410845560db2f05fd2140e4f993f47283c060b9ec63eab72c254091bb601103b081912b6a6385e882c09fd686806bd2bf476 @@ -18842,7 +18851,7 @@ __metadata: languageName: node linkType: hard -"smol-toml@npm:^1.4.2, smol-toml@npm:^1.5.2, smol-toml@npm:~1.5.2": +"smol-toml@npm:^1.5.2, smol-toml@npm:~1.5.2": version: 1.5.2 resolution: "smol-toml@npm:1.5.2" checksum: 75b7e8482151cbe48be094de205631502d5694c2a7d968446799e8b988b4105bd6efd3b6a986baa40d9e9b47cbb2daada21a302901a618793aabd35a670f195e @@ -21283,12 +21292,12 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.6.0, yaml@npm:^2.7.0, yaml@npm:^2.7.1, yaml@npm:^2.8.1": - version: 2.8.1 - resolution: "yaml@npm:2.8.1" +"yaml@npm:^2.6.0, yaml@npm:^2.7.0, yaml@npm:^2.7.1, yaml@npm:^2.8.2": + version: 2.8.2 + resolution: "yaml@npm:2.8.2" bin: yaml: bin.mjs - checksum: 35b46150d48bc1da2fd5b1521a48a4fa36d68deaabe496f3c3fa9646d5796b6b974f3930a02c4b5aee6c85c860d7d7f79009416724465e835f40b87898c36de4 + checksum: 5ffd9f23bc7a450129cbd49dcf91418988f154ede10c83fd28ab293661ac2783c05da19a28d76a22cbd77828eae25d4bd7453f9a9fe2d287d085d72db46fd105 languageName: node linkType: hard From 5bd78cab52569a5e9e14a8e4588a672ca933a0be Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 12 Dec 2025 10:30:40 -0700 Subject: [PATCH 2/3] chore(deps): update dependency console-fail-test to ^0.6.0 (#11841) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 7fe68c15c5f..ee353f13d27 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "@typescript-eslint/utils": "workspace:^", "@vitest/coverage-v8": "^3.1.3", "@vitest/eslint-plugin": "1.5.1", - "console-fail-test": "^0.5.0", + "console-fail-test": "^0.6.0", "cross-fetch": "^4.0.0", "cspell": "^9.0.0", "eslint": "^9.26.0", diff --git a/yarn.lock b/yarn.lock index eff9f91cd8b..47039b5e7d9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6376,7 +6376,7 @@ __metadata: "@typescript-eslint/utils": "workspace:^" "@vitest/coverage-v8": ^3.1.3 "@vitest/eslint-plugin": 1.5.1 - console-fail-test: ^0.5.0 + console-fail-test: ^0.6.0 cross-fetch: ^4.0.0 cspell: ^9.0.0 eslint: ^9.26.0 @@ -8564,10 +8564,10 @@ __metadata: languageName: node linkType: hard -"console-fail-test@npm:^0.5.0": - version: 0.5.0 - resolution: "console-fail-test@npm:0.5.0" - checksum: 61ccd9f6c034dbbba8acb0dcfe8c9dec1e5c6da69e1f365786468065a209fc1ee4acca70048e48d6149d5f0e89ae3c835c0b4c2698300f334614f65029c63484 +"console-fail-test@npm:^0.6.0": + version: 0.6.1 + resolution: "console-fail-test@npm:0.6.1" + checksum: 6e0e30d95d195b234e927a6b9c92a8e8346fb2e4eaccd9dacc2fde54ce0f82f2ad483f7585a4deefb7b101ded3dbcc7eb36c3584c4541ff7fa39941d6a93a470 languageName: node linkType: hard From 1301f79e54241c1760ef88a76a757bc498d9a840 Mon Sep 17 00:00:00 2001 From: Ulrich Stark Date: Sun, 14 Dec 2025 15:43:10 +0100 Subject: [PATCH 3/3] feat(eslint-plugin): [no-useless-default-assignment] add rule (#11720) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(eslint-plugin): [no-useless-default-assignment] add rule * support function parameters without type annotation * fix false positives * fixing more false positives * enable rule in repo to dogfood * cleanup code and increase code coverage * cleanup code and add column numbers to tests * add tests to increase test coverage * remove option allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing * remove comments at each test case * remove rule from rulesWithComplexOptionHeadings * update snapshot * Update packages/eslint-plugin/docs/rules/no-useless-default-assignment.mdx Co-authored-by: Josh Goldberg ✨ * Update packages/eslint-plugin/docs/rules/no-useless-default-assignment.mdx Co-authored-by: Josh Goldberg ✨ * add rule to strict config * turn suggestion into fix * add more test cases and make them pass * make example code easier to understand and add tuple example * increase test coverage * remove self-apparent comments * use createRuleTesterWithTypes * use isFunction * remove unnecessary schema item * update snapshot * support nested destructuring * add valid test case * report contextual assignments and more test cases * report undefined as useless default assignment * add test cases, refactor and use nullThrows to increase test coverage * remove from eslint.config.mjs * make "when not to use it" more relevant to this rule * remove unnecessary type assertion * check for string index type * support compiler option noUncheckedIndexedAccess properly * also support noUncheckedIndexedAccess for records/mapped types --------- Co-authored-by: Josh Goldberg ✨ --- .../rules/no-useless-default-assignment.mdx | 53 ++ .../eslint-plugin/src/configs/eslintrc/all.ts | 1 + .../configs/eslintrc/disable-type-checked.ts | 1 + .../eslintrc/strict-type-checked-only.ts | 1 + .../configs/eslintrc/strict-type-checked.ts | 1 + .../eslint-plugin/src/configs/flat/all.ts | 1 + .../src/configs/flat/disable-type-checked.ts | 1 + .../configs/flat/strict-type-checked-only.ts | 1 + .../src/configs/flat/strict-type-checked.ts | 1 + packages/eslint-plugin/src/rules/index.ts | 2 + .../rules/no-useless-default-assignment.ts | 263 +++++++++ .../no-useless-default-assignment.shot | 27 + .../no-useless-default-assignment.test.ts | 520 ++++++++++++++++++ .../no-useless-default-assignment.shot | 10 + 14 files changed, 883 insertions(+) create mode 100644 packages/eslint-plugin/docs/rules/no-useless-default-assignment.mdx create mode 100644 packages/eslint-plugin/src/rules/no-useless-default-assignment.ts create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-useless-default-assignment.shot create mode 100644 packages/eslint-plugin/tests/rules/no-useless-default-assignment.test.ts create mode 100644 packages/eslint-plugin/tests/schema-snapshots/no-useless-default-assignment.shot diff --git a/packages/eslint-plugin/docs/rules/no-useless-default-assignment.mdx b/packages/eslint-plugin/docs/rules/no-useless-default-assignment.mdx new file mode 100644 index 00000000000..258e9b5b812 --- /dev/null +++ b/packages/eslint-plugin/docs/rules/no-useless-default-assignment.mdx @@ -0,0 +1,53 @@ +--- +description: 'Disallow default values that will never be used.' +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +> 🛑 This file is source code, not the primary documentation location! 🛑 +> +> See **https://typescript-eslint.io/rules/no-useless-default-assignment** for documentation. + +[Default parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters) and [default values](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#default_value) are only used if the parameter or property is `undefined`. +That can happen when a value is missing, or when one is provided and set to `undefined`. +If a non-`undefined` value is guaranteed to be provided, then there is no need to define a default. + +## Examples + + + + +```ts +function Bar({ foo = '' }: { foo: string }) { + return foo; +} + +const { foo = '' } = { foo: 'bar' }; + +const [foo = ''] = ['bar']; + +[1, 2, 3].map((a = 42) => a + 1); +``` + + + + +```ts +function Bar({ foo = '' }: { foo?: string }) { + return foo; +} + +const { foo = '' } = { foo: undefined }; + +const [foo = ''] = [undefined]; + +[1, 2, 3, undefined].map((a = 42) => a + 1); +``` + + + + +## When Not To Use It + +If you use default values defensively against runtime values that bypass type checking, or for documentation purposes, you may want to disable this rule. diff --git a/packages/eslint-plugin/src/configs/eslintrc/all.ts b/packages/eslint-plugin/src/configs/eslintrc/all.ts index 78c8420e264..11221a74807 100644 --- a/packages/eslint-plugin/src/configs/eslintrc/all.ts +++ b/packages/eslint-plugin/src/configs/eslintrc/all.ts @@ -120,6 +120,7 @@ export = { '@typescript-eslint/no-use-before-define': 'error', 'no-useless-constructor': 'off', '@typescript-eslint/no-useless-constructor': 'error', + '@typescript-eslint/no-useless-default-assignment': 'error', '@typescript-eslint/no-useless-empty-export': 'error', '@typescript-eslint/no-wrapper-object-types': 'error', '@typescript-eslint/non-nullable-type-assertion-style': 'error', diff --git a/packages/eslint-plugin/src/configs/eslintrc/disable-type-checked.ts b/packages/eslint-plugin/src/configs/eslintrc/disable-type-checked.ts index 6853a151722..277f99228c1 100644 --- a/packages/eslint-plugin/src/configs/eslintrc/disable-type-checked.ts +++ b/packages/eslint-plugin/src/configs/eslintrc/disable-type-checked.ts @@ -44,6 +44,7 @@ export = { '@typescript-eslint/no-unsafe-return': 'off', '@typescript-eslint/no-unsafe-type-assertion': 'off', '@typescript-eslint/no-unsafe-unary-minus': 'off', + '@typescript-eslint/no-useless-default-assignment': 'off', '@typescript-eslint/non-nullable-type-assertion-style': 'off', '@typescript-eslint/only-throw-error': 'off', '@typescript-eslint/prefer-destructuring': 'off', diff --git a/packages/eslint-plugin/src/configs/eslintrc/strict-type-checked-only.ts b/packages/eslint-plugin/src/configs/eslintrc/strict-type-checked-only.ts index a2b5b457d01..c455ac88371 100644 --- a/packages/eslint-plugin/src/configs/eslintrc/strict-type-checked-only.ts +++ b/packages/eslint-plugin/src/configs/eslintrc/strict-type-checked-only.ts @@ -39,6 +39,7 @@ export = { '@typescript-eslint/no-unsafe-member-access': 'error', '@typescript-eslint/no-unsafe-return': 'error', '@typescript-eslint/no-unsafe-unary-minus': 'error', + '@typescript-eslint/no-useless-default-assignment': 'error', 'no-throw-literal': 'off', '@typescript-eslint/only-throw-error': 'error', 'prefer-promise-reject-errors': 'off', diff --git a/packages/eslint-plugin/src/configs/eslintrc/strict-type-checked.ts b/packages/eslint-plugin/src/configs/eslintrc/strict-type-checked.ts index ec1523d8b48..aba8c3006a1 100644 --- a/packages/eslint-plugin/src/configs/eslintrc/strict-type-checked.ts +++ b/packages/eslint-plugin/src/configs/eslintrc/strict-type-checked.ts @@ -68,6 +68,7 @@ export = { '@typescript-eslint/no-unused-vars': 'error', 'no-useless-constructor': 'off', '@typescript-eslint/no-useless-constructor': 'error', + '@typescript-eslint/no-useless-default-assignment': 'error', '@typescript-eslint/no-wrapper-object-types': 'error', 'no-throw-literal': 'off', '@typescript-eslint/only-throw-error': 'error', diff --git a/packages/eslint-plugin/src/configs/flat/all.ts b/packages/eslint-plugin/src/configs/flat/all.ts index 43792419ab3..7e61ed948ab 100644 --- a/packages/eslint-plugin/src/configs/flat/all.ts +++ b/packages/eslint-plugin/src/configs/flat/all.ts @@ -134,6 +134,7 @@ export default ( '@typescript-eslint/no-use-before-define': 'error', 'no-useless-constructor': 'off', '@typescript-eslint/no-useless-constructor': 'error', + '@typescript-eslint/no-useless-default-assignment': 'error', '@typescript-eslint/no-useless-empty-export': 'error', '@typescript-eslint/no-wrapper-object-types': 'error', '@typescript-eslint/non-nullable-type-assertion-style': 'error', diff --git a/packages/eslint-plugin/src/configs/flat/disable-type-checked.ts b/packages/eslint-plugin/src/configs/flat/disable-type-checked.ts index 5a48e172277..7603dde91c7 100644 --- a/packages/eslint-plugin/src/configs/flat/disable-type-checked.ts +++ b/packages/eslint-plugin/src/configs/flat/disable-type-checked.ts @@ -51,6 +51,7 @@ export default ( '@typescript-eslint/no-unsafe-return': 'off', '@typescript-eslint/no-unsafe-type-assertion': 'off', '@typescript-eslint/no-unsafe-unary-minus': 'off', + '@typescript-eslint/no-useless-default-assignment': 'off', '@typescript-eslint/non-nullable-type-assertion-style': 'off', '@typescript-eslint/only-throw-error': 'off', '@typescript-eslint/prefer-destructuring': 'off', diff --git a/packages/eslint-plugin/src/configs/flat/strict-type-checked-only.ts b/packages/eslint-plugin/src/configs/flat/strict-type-checked-only.ts index 043f1aad0cd..2cddf49a463 100644 --- a/packages/eslint-plugin/src/configs/flat/strict-type-checked-only.ts +++ b/packages/eslint-plugin/src/configs/flat/strict-type-checked-only.ts @@ -52,6 +52,7 @@ export default ( '@typescript-eslint/no-unsafe-member-access': 'error', '@typescript-eslint/no-unsafe-return': 'error', '@typescript-eslint/no-unsafe-unary-minus': 'error', + '@typescript-eslint/no-useless-default-assignment': 'error', 'no-throw-literal': 'off', '@typescript-eslint/only-throw-error': 'error', 'prefer-promise-reject-errors': 'off', diff --git a/packages/eslint-plugin/src/configs/flat/strict-type-checked.ts b/packages/eslint-plugin/src/configs/flat/strict-type-checked.ts index b3c0a239117..4d34eb4925d 100644 --- a/packages/eslint-plugin/src/configs/flat/strict-type-checked.ts +++ b/packages/eslint-plugin/src/configs/flat/strict-type-checked.ts @@ -81,6 +81,7 @@ export default ( '@typescript-eslint/no-unused-vars': 'error', 'no-useless-constructor': 'off', '@typescript-eslint/no-useless-constructor': 'error', + '@typescript-eslint/no-useless-default-assignment': 'error', '@typescript-eslint/no-wrapper-object-types': 'error', 'no-throw-literal': 'off', '@typescript-eslint/only-throw-error': 'error', diff --git a/packages/eslint-plugin/src/rules/index.ts b/packages/eslint-plugin/src/rules/index.ts index 9ee5903aa5f..c32c3296751 100644 --- a/packages/eslint-plugin/src/rules/index.ts +++ b/packages/eslint-plugin/src/rules/index.ts @@ -92,6 +92,7 @@ import noUnusedPrivateClassMembers from './no-unused-private-class-members'; import noUnusedVars from './no-unused-vars'; import noUseBeforeDefine from './no-use-before-define'; import noUselessConstructor from './no-useless-constructor'; +import noUselessDefaultAssignment from './no-useless-default-assignment'; import noUselessEmptyExport from './no-useless-empty-export'; import noVarRequires from './no-var-requires'; import noWrapperObjectTypes from './no-wrapper-object-types'; @@ -227,6 +228,7 @@ const rules = { 'no-unused-vars': noUnusedVars, 'no-use-before-define': noUseBeforeDefine, 'no-useless-constructor': noUselessConstructor, + 'no-useless-default-assignment': noUselessDefaultAssignment, 'no-useless-empty-export': noUselessEmptyExport, 'no-var-requires': noVarRequires, 'no-wrapper-object-types': noWrapperObjectTypes, diff --git a/packages/eslint-plugin/src/rules/no-useless-default-assignment.ts b/packages/eslint-plugin/src/rules/no-useless-default-assignment.ts new file mode 100644 index 00000000000..f33631df44a --- /dev/null +++ b/packages/eslint-plugin/src/rules/no-useless-default-assignment.ts @@ -0,0 +1,263 @@ +import type { TSESTree } from '@typescript-eslint/utils'; + +import { AST_NODE_TYPES } from '@typescript-eslint/utils'; +import * as tsutils from 'ts-api-utils'; +import * as ts from 'typescript'; + +import { + createRule, + getParserServices, + isFunction, + isTypeAnyType, + isTypeFlagSet, + isTypeUnknownType, + nullThrows, + NullThrowsReasons, +} from '../util'; + +type MessageId = 'uselessDefaultAssignment' | 'uselessUndefined'; + +export default createRule<[], MessageId>({ + name: 'no-useless-default-assignment', + meta: { + type: 'suggestion', + docs: { + description: 'Disallow default values that will never be used', + recommended: 'strict', + requiresTypeChecking: true, + }, + fixable: 'code', + messages: { + uselessDefaultAssignment: + 'Default value is useless because the {{ type }} is not optional.', + uselessUndefined: + 'Default value is useless because it is undefined. Optional {{ type }}s are already undefined by default.', + }, + schema: [], + }, + defaultOptions: [], + create(context) { + const services = getParserServices(context); + const checker = services.program.getTypeChecker(); + const compilerOptions = services.program.getCompilerOptions(); + const isNoUncheckedIndexedAccess = tsutils.isCompilerOptionEnabled( + compilerOptions, + 'noUncheckedIndexedAccess', + ); + + function canBeUndefined(type: ts.Type): boolean { + if (isTypeAnyType(type) || isTypeUnknownType(type)) { + return true; + } + return tsutils + .unionConstituents(type) + .some(part => isTypeFlagSet(part, ts.TypeFlags.Undefined)); + } + + function getPropertyType( + objectType: ts.Type, + propertyName: string, + ): ts.Type | null { + const symbol = objectType.getProperty(propertyName); + if (!symbol) { + if (isNoUncheckedIndexedAccess) { + return null; + } + return objectType.getStringIndexType() ?? null; + } + return checker.getTypeOfSymbol(symbol); + } + + function getArrayElementType( + arrayType: ts.Type, + elementIndex: number, + ): ts.Type | null { + if (checker.isTupleType(arrayType)) { + const tupleArgs = checker.getTypeArguments(arrayType); + if (elementIndex < tupleArgs.length) { + return tupleArgs[elementIndex]; + } + } + + if (isNoUncheckedIndexedAccess) { + return null; + } + + return arrayType.getNumberIndexType() ?? null; + } + + function checkAssignmentPattern(node: TSESTree.AssignmentPattern): void { + if ( + node.right.type === AST_NODE_TYPES.Identifier && + node.right.name === 'undefined' + ) { + const type = + node.parent.type === AST_NODE_TYPES.Property || + node.parent.type === AST_NODE_TYPES.ArrayPattern + ? 'property' + : 'parameter'; + reportUselessDefault(node, type, 'uselessUndefined'); + return; + } + + const parent = node.parent; + + if ( + parent.type === AST_NODE_TYPES.ArrowFunctionExpression || + parent.type === AST_NODE_TYPES.FunctionExpression + ) { + const paramIndex = parent.params.indexOf(node); + if (paramIndex !== -1) { + const tsFunc = services.esTreeNodeToTSNodeMap.get(parent); + if (ts.isFunctionLike(tsFunc)) { + const contextualType = checker.getContextualType( + tsFunc as ts.Expression, + ); + if (!contextualType) { + return; + } + + const signatures = contextualType.getCallSignatures(); + const params = signatures[0].getParameters(); + if (paramIndex < params.length) { + const paramSymbol = params[paramIndex]; + if ((paramSymbol.flags & ts.SymbolFlags.Optional) === 0) { + const paramType = checker.getTypeOfSymbol(paramSymbol); + if (!canBeUndefined(paramType)) { + reportUselessDefault( + node, + 'parameter', + 'uselessDefaultAssignment', + ); + } + } + } + } + } + return; + } + + if (parent.type === AST_NODE_TYPES.Property) { + const propertyType = getTypeOfProperty(parent); + if (!propertyType) { + return; + } + + if (!canBeUndefined(propertyType)) { + reportUselessDefault(node, 'property', 'uselessDefaultAssignment'); + } + } else if (parent.type === AST_NODE_TYPES.ArrayPattern) { + const sourceType = getSourceTypeForPattern(parent); + if (!sourceType) { + return; + } + + const elementIndex = parent.elements.indexOf(node); + const elementType = getArrayElementType(sourceType, elementIndex); + if (!elementType) { + return; + } + + if (!canBeUndefined(elementType)) { + reportUselessDefault(node, 'property', 'uselessDefaultAssignment'); + } + } + } + + function getTypeOfProperty(node: TSESTree.Property): ts.Type | null { + const objectPattern = node.parent as TSESTree.ObjectPattern; + const sourceType = getSourceTypeForPattern(objectPattern); + if (!sourceType) { + return null; + } + + const propertyName = getPropertyName(node.key); + if (!propertyName) { + return null; + } + + return getPropertyType(sourceType, propertyName); + } + + function getSourceTypeForPattern(pattern: TSESTree.Node): ts.Type | null { + const parent = nullThrows( + pattern.parent, + NullThrowsReasons.MissingParent, + ); + + if (parent.type === AST_NODE_TYPES.VariableDeclarator && parent.init) { + const tsNode = services.esTreeNodeToTSNodeMap.get(parent.init); + return checker.getTypeAtLocation(tsNode); + } + + if (isFunction(parent)) { + const paramIndex = parent.params.indexOf(pattern as TSESTree.Parameter); + const tsFunc = services.esTreeNodeToTSNodeMap.get(parent); + const signature = nullThrows( + checker.getSignatureFromDeclaration(tsFunc), + NullThrowsReasons.MissingToken('signature', 'function'), + ); + const params = signature.getParameters(); + return checker.getTypeOfSymbol(params[paramIndex]); + } + + if (parent.type === AST_NODE_TYPES.AssignmentPattern) { + return getSourceTypeForPattern(parent); + } + + if (parent.type === AST_NODE_TYPES.Property) { + return getTypeOfProperty(parent); + } + + if (parent.type === AST_NODE_TYPES.ArrayPattern) { + const arrayPattern = parent; + const arrayType = getSourceTypeForPattern(arrayPattern); + if (!arrayType) { + return null; + } + const elementIndex = arrayPattern.elements.indexOf( + pattern as TSESTree.DestructuringPattern, + ); + return getArrayElementType(arrayType, elementIndex); + } + + return null; + } + + function getPropertyName( + key: TSESTree.Expression | TSESTree.PrivateIdentifier, + ): string | null { + switch (key.type) { + case AST_NODE_TYPES.Identifier: + return key.name; + case AST_NODE_TYPES.Literal: + return String(key.value); + default: + return null; + } + } + + function reportUselessDefault( + node: TSESTree.AssignmentPattern, + type: 'parameter' | 'property', + messageId: MessageId, + ): void { + context.report({ + node: node.right, + messageId, + data: { type }, + fix(fixer) { + // Remove from before the = to the end of the default value + // Find the start position (including whitespace before =) + const start = node.left.range[1]; + const end = node.range[1]; + return fixer.removeRange([start, end]); + }, + }); + } + + return { + AssignmentPattern: checkAssignmentPattern, + }; + }, +}); diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-useless-default-assignment.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-useless-default-assignment.shot new file mode 100644 index 00000000000..b63ea9a740f --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-useless-default-assignment.shot @@ -0,0 +1,27 @@ +Incorrect + +function Bar({ foo = '' }: { foo: string }) { + ~~ Default value is useless because the property is not optional. + return foo; +} + +const { foo = '' } = { foo: 'bar' }; + ~~ Default value is useless because the property is not optional. + +const [foo = ''] = ['bar']; + ~~ Default value is useless because the property is not optional. + +[1, 2, 3].map((a = 42) => a + 1); + ~~ Default value is useless because the parameter is not optional. + +Correct + +function Bar({ foo = '' }: { foo?: string }) { + return foo; +} + +const { foo = '' } = { foo: undefined }; + +const [foo = ''] = [undefined]; + +[1, 2, 3, undefined].map((a = 42) => a + 1); diff --git a/packages/eslint-plugin/tests/rules/no-useless-default-assignment.test.ts b/packages/eslint-plugin/tests/rules/no-useless-default-assignment.test.ts new file mode 100644 index 00000000000..d5d52b5bd0d --- /dev/null +++ b/packages/eslint-plugin/tests/rules/no-useless-default-assignment.test.ts @@ -0,0 +1,520 @@ +import rule from '../../src/rules/no-useless-default-assignment'; +import { createRuleTesterWithTypes, getFixturesRootDir } from '../RuleTester'; + +const rootDir = getFixturesRootDir(); +const ruleTester = createRuleTesterWithTypes(); + +ruleTester.run('no-useless-default-assignment', rule, { + valid: [ + ` + function Bar({ foo = '' }: { foo?: string }) { + return foo; + } + `, + ` + const { foo } = { foo: 'bar' }; + `, + ` + [1, 2, 3, undefined].map((a = 42) => a + 1); + `, + ` + function test(a?: number) { + return a; + } + `, + ` + const obj: { a?: string } = {}; + const { a = 'default' } = obj; + `, + ` + function test(a: string | undefined = 'default') { + return a; + } + `, + ` + (a: string = 'default') => a; + `, + ` + function test(a: string = 'default') { + return a; + } + `, + ` + class C { + public test(a: string = 'default') { + return a; + } + } + `, + ` + const obj: { a: string | undefined } = { a: undefined }; + const { a = 'default' } = obj; + `, + ` + function test(arr: number[] | undefined = []) { + return arr; + } + `, + ` + function Bar({ nested: { foo = '' } = {} }: { nested?: { foo?: string } }) { + return foo; + } + `, + ` + function test(a: any = 'default') { + return a; + } + `, + ` + function test(a: unknown = 'default') { + return a; + } + `, + ` + function test(a = 5) { + return a; + } + `, + ` + function createValidator(): () => void { + return (param = 5) => {}; + } + `, + ` + function Bar({ foo = '' }: { foo: any }) { + return foo; + } + `, + ` + function Bar({ foo = '' }: { foo: unknown }) { + return foo; + } + `, + ` + function getValue(): undefined; + function getValue(box: { value: string }): string; + function getValue({ value = '' }: { value?: string } = {}): string | undefined { + return value; + } + `, + ` + function getValueObject({ value = '' }: Partial<{ value: string }>) { + return value; + } + `, + ` + const { value = 'default' } = someUnknownFunction(); + `, + ` + const [value = 'default'] = someUnknownFunction(); + `, + ` + for (const { value = 'default' } of []) { + } + `, + ` + for (const [value = 'default'] of []) { + } + `, + ` + declare const x: [[number | undefined]]; + const [[a = 1]] = x; + `, + ` + function foo(x: string = '') {} + `, + ` + class C { + method(x: string = '') {} + } + `, + ` + const foo = (x: string = '') => {}; + `, + ` + const obj = { ab: { x: 1 } }; + const { + ['a' + 'b']: { x = 1 }, + } = obj; + `, + ` + const obj = { ab: 1 }; + const { ['a' + 'b']: x = 1 } = obj; + `, + ` + for ([[a = 1]] of []) { + } + `, + { + code: ` + declare const g: Array; + const [foo = ''] = g; + `, + languageOptions: { + parserOptions: { + project: './tsconfig.noUncheckedIndexedAccess.json', + projectService: false, + tsconfigRootDir: rootDir, + }, + }, + }, + { + code: ` + declare const g: Record; + const { foo = '' } = g; + `, + languageOptions: { + parserOptions: { + project: './tsconfig.noUncheckedIndexedAccess.json', + projectService: false, + tsconfigRootDir: rootDir, + }, + }, + }, + { + code: ` + declare const h: { [key: string]: string }; + const { bar = '' } = h; + `, + languageOptions: { + parserOptions: { + project: './tsconfig.noUncheckedIndexedAccess.json', + projectService: false, + tsconfigRootDir: rootDir, + }, + }, + }, + ], + invalid: [ + { + code: ` + function Bar({ foo = '' }: { foo: string }) { + return foo; + } + `, + errors: [ + { + column: 30, + data: { type: 'property' }, + endColumn: 32, + line: 2, + messageId: 'uselessDefaultAssignment', + }, + ], + output: ` + function Bar({ foo }: { foo: string }) { + return foo; + } + `, + }, + { + code: ` + class C { + public method({ foo = '' }: { foo: string }) { + return foo; + } + } + `, + errors: [ + { + column: 33, + data: { type: 'property' }, + endColumn: 35, + line: 3, + messageId: 'uselessDefaultAssignment', + }, + ], + output: ` + class C { + public method({ foo }: { foo: string }) { + return foo; + } + } + `, + }, + { + code: ` + const { 'literal-key': literalKey = 'default' } = { 'literal-key': 'value' }; + `, + errors: [ + { + column: 45, + data: { type: 'property' }, + endColumn: 54, + line: 2, + messageId: 'uselessDefaultAssignment', + }, + ], + output: ` + const { 'literal-key': literalKey } = { 'literal-key': 'value' }; + `, + }, + { + code: ` + [1, 2, 3].map((a = 42) => a + 1); + `, + errors: [ + { + column: 28, + data: { type: 'parameter' }, + endColumn: 30, + line: 2, + messageId: 'uselessDefaultAssignment', + }, + ], + output: ` + [1, 2, 3].map((a) => a + 1); + `, + }, + { + code: ` + function getValue(): undefined; + function getValue(box: { value: string }): string; + function getValue({ value = '' }: { value: string } = {}): string | undefined { + return value; + } + `, + errors: [ + { + column: 37, + data: { type: 'property' }, + endColumn: 39, + line: 4, + messageId: 'uselessDefaultAssignment', + }, + ], + output: ` + function getValue(): undefined; + function getValue(box: { value: string }): string; + function getValue({ value }: { value: string } = {}): string | undefined { + return value; + } + `, + }, + { + code: ` + function getValue([value = '']: [string]) { + return value; + } + `, + errors: [ + { + column: 36, + data: { type: 'property' }, + endColumn: 38, + line: 2, + messageId: 'uselessDefaultAssignment', + }, + ], + output: ` + function getValue([value]: [string]) { + return value; + } + `, + }, + { + code: ` + declare const x: { hello: { world: string } }; + + const { + hello: { world = '' }, + } = x; + `, + errors: [ + { + column: 28, + data: { type: 'property' }, + endColumn: 30, + line: 5, + messageId: 'uselessDefaultAssignment', + }, + ], + output: ` + declare const x: { hello: { world: string } }; + + const { + hello: { world }, + } = x; + `, + }, + { + code: ` + declare const x: { hello: Array<{ world: string }> }; + + const { + hello: [{ world = '' }], + } = x; + `, + errors: [ + { + column: 29, + data: { type: 'property' }, + endColumn: 31, + line: 5, + messageId: 'uselessDefaultAssignment', + }, + ], + output: ` + declare const x: { hello: Array<{ world: string }> }; + + const { + hello: [{ world }], + } = x; + `, + }, + { + code: ` + interface B { + foo: (b: boolean | string) => void; + } + + const h: B = { + foo: (b = false) => {}, + }; + `, + errors: [ + { + column: 21, + data: { type: 'parameter' }, + endColumn: 26, + line: 7, + messageId: 'uselessDefaultAssignment', + }, + ], + output: ` + interface B { + foo: (b: boolean | string) => void; + } + + const h: B = { + foo: (b) => {}, + }; + `, + }, + { + code: ` + function foo(a = undefined) {} + `, + errors: [ + { + column: 26, + data: { type: 'parameter' }, + endColumn: 35, + line: 2, + messageId: 'uselessUndefined', + }, + ], + output: ` + function foo(a) {} + `, + }, + { + code: ` + const { a = undefined } = {}; + `, + errors: [ + { + column: 21, + data: { type: 'property' }, + endColumn: 30, + line: 2, + messageId: 'uselessUndefined', + }, + ], + output: ` + const { a } = {}; + `, + }, + { + code: ` + const [a = undefined] = []; + `, + errors: [ + { + column: 20, + data: { type: 'property' }, + endColumn: 29, + line: 2, + messageId: 'uselessUndefined', + }, + ], + output: ` + const [a] = []; + `, + }, + { + code: ` + function foo({ a = undefined }) {} + `, + errors: [ + { + column: 28, + data: { type: 'property' }, + endColumn: 37, + line: 2, + messageId: 'uselessUndefined', + }, + ], + output: ` + function foo({ a }) {} + `, + }, + { + code: ` + declare const g: Record; + const { hello = '' } = g; + `, + errors: [ + { + column: 25, + data: { type: 'property' }, + endColumn: 27, + line: 3, + messageId: 'uselessDefaultAssignment', + }, + ], + output: ` + declare const g: Record; + const { hello } = g; + `, + }, + { + code: ` + declare const h: { [key: string]: string }; + const { world = '' } = h; + `, + errors: [ + { + column: 25, + data: { type: 'property' }, + endColumn: 27, + line: 3, + messageId: 'uselessDefaultAssignment', + }, + ], + output: ` + declare const h: { [key: string]: string }; + const { world } = h; + `, + }, + { + code: ` + declare const g: Array; + const [foo = ''] = g; + `, + errors: [ + { + column: 22, + data: { type: 'property' }, + endColumn: 24, + line: 3, + messageId: 'uselessDefaultAssignment', + }, + ], + output: ` + declare const g: Array; + const [foo] = g; + `, + }, + ], +}); diff --git a/packages/eslint-plugin/tests/schema-snapshots/no-useless-default-assignment.shot b/packages/eslint-plugin/tests/schema-snapshots/no-useless-default-assignment.shot new file mode 100644 index 00000000000..cdd9f837585 --- /dev/null +++ b/packages/eslint-plugin/tests/schema-snapshots/no-useless-default-assignment.shot @@ -0,0 +1,10 @@ + +# SCHEMA: + +[] + + +# TYPES: + +/** No options declared */ +type Options = [];