Skip to content

Commit f8903df

Browse files
Merge branch 'main' into feature/tscofing-view-error
2 parents a619ba6 + 5b187f4 commit f8903df

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1732
-297
lines changed

Diff for: CHANGELOG.md

+17
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
## 8.28.0 (2025-03-24)
2+
3+
### 🚀 Features
4+
5+
- **eslint-plugin:** [prefer-nullish-coalescing] support `if` statement assignment (`??=`) and fix several minor bugs ([#10861](https://github.com/typescript-eslint/typescript-eslint/pull/10861))
6+
7+
### 🩹 Fixes
8+
9+
- **eslint-plugin:** [no-unsafe-function-type] remove fixable property ([#10986](https://github.com/typescript-eslint/typescript-eslint/pull/10986))
10+
11+
### ❤️ Thank You
12+
13+
- Olivier Zalmanski @OlivierZal
14+
- Yannick Decat @mho22
15+
16+
You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.
17+
118
## 8.27.0 (2025-03-17)
219

320
### 🚀 Features

Diff for: eslint.config.mjs

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const restrictNamedDeclarations = {
3131

3232
const vitestFiles = [
3333
'packages/eslint-plugin-internal/tests/**/*.test.{ts,tsx,cts,mts}',
34+
'packages/typescript-eslint/tests/**/*.test.{ts,tsx,cts,mts}',
3435
];
3536

3637
export default tseslint.config(

Diff for: packages/ast-spec/CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 8.28.0 (2025-03-24)
2+
3+
This was a version bump only for ast-spec to align it with other projects, there were no code changes.
4+
5+
You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.
6+
17
## 8.27.0 (2025-03-17)
28

39
### 🩹 Fixes

Diff for: packages/ast-spec/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@typescript-eslint/ast-spec",
3-
"version": "8.27.0",
3+
"version": "8.28.0",
44
"description": "Complete specification for the TypeScript-ESTree AST",
55
"private": true,
66
"keywords": [

Diff for: packages/eslint-plugin/CHANGELOG.md

+17
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
## 8.28.0 (2025-03-24)
2+
3+
### 🚀 Features
4+
5+
- **eslint-plugin:** [prefer-nullish-coalescing] support `if` statement assignment (`??=`) and fix several minor bugs ([#10861](https://github.com/typescript-eslint/typescript-eslint/pull/10861))
6+
7+
### 🩹 Fixes
8+
9+
- **eslint-plugin:** [no-unsafe-function-type] remove fixable property ([#10986](https://github.com/typescript-eslint/typescript-eslint/pull/10986))
10+
11+
### ❤️ Thank You
12+
13+
- Olivier Zalmanski @OlivierZal
14+
- Yannick Decat @mho22
15+
16+
You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.
17+
118
## 8.27.0 (2025-03-17)
219

320
### 🚀 Features

Diff for: packages/eslint-plugin/docs/rules/prefer-nullish-coalescing.mdx

+49
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,54 @@ This rule reports when you may consider replacing:
1717
- An `||` operator with `??`
1818
- An `||=` operator with `??=`
1919
- Ternary expressions (`?:`) that are equivalent to `||` or `??` with `??`
20+
- Assignment expressions (`=`) that can be safely replaced by `??=`
21+
22+
## Examples
23+
24+
<Tabs>
25+
<TabItem value="❌ Incorrect">
26+
27+
```ts
28+
declare const a: string | null;
29+
declare const b: string | null;
30+
31+
const c = a || b;
32+
33+
declare let foo: { a: string } | null;
34+
declare function makeFoo(): { a: string };
35+
36+
function lazyInitializeFooByTruthiness() {
37+
if (!foo) {
38+
foo = makeFoo();
39+
}
40+
}
41+
42+
function lazyInitializeFooByNullCheck() {
43+
if (foo == null) {
44+
foo = makeFoo();
45+
}
46+
}
47+
```
48+
49+
</TabItem>
50+
<TabItem value="✅ Correct">
51+
52+
```ts
53+
declare const a: string | null;
54+
declare const b: string | null;
55+
56+
const c = a ?? b;
57+
58+
declare let foo: { a: string } | null;
59+
declare function makeFoo(): { a: string };
60+
61+
function lazyInitializeFoo() {
62+
foo ??= makeFoo();
63+
}
64+
```
65+
66+
</TabItem>
67+
</Tabs>
2068

2169
:::caution
2270
This rule will not work as expected if [`strictNullChecks`](https://www.typescriptlang.org/tsconfig#strictNullChecks) is not enabled.
@@ -255,3 +303,4 @@ If you are not using TypeScript 3.7 (or greater), then you will not be able to u
255303

256304
- [TypeScript 3.7 Release Notes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html)
257305
- [Nullish Coalescing Operator Proposal](https://github.com/tc39/proposal-nullish-coalescing/)
306+
- [`logical-assignment-operators`](https://eslint.org/docs/latest/rules/logical-assignment-operators)

Diff for: packages/eslint-plugin/package.json

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@typescript-eslint/eslint-plugin",
3-
"version": "8.27.0",
3+
"version": "8.28.0",
44
"description": "TypeScript plugin for ESLint",
55
"files": [
66
"dist",
@@ -62,10 +62,10 @@
6262
},
6363
"dependencies": {
6464
"@eslint-community/regexpp": "^4.10.0",
65-
"@typescript-eslint/scope-manager": "8.27.0",
66-
"@typescript-eslint/type-utils": "8.27.0",
67-
"@typescript-eslint/utils": "8.27.0",
68-
"@typescript-eslint/visitor-keys": "8.27.0",
65+
"@typescript-eslint/scope-manager": "8.28.0",
66+
"@typescript-eslint/type-utils": "8.28.0",
67+
"@typescript-eslint/utils": "8.28.0",
68+
"@typescript-eslint/visitor-keys": "8.28.0",
6969
"graphemer": "^1.4.0",
7070
"ignore": "^5.3.1",
7171
"natural-compare": "^1.4.0",
@@ -76,8 +76,8 @@
7676
"@types/marked": "^5.0.2",
7777
"@types/mdast": "^4.0.3",
7878
"@types/natural-compare": "*",
79-
"@typescript-eslint/rule-schema-to-typescript-types": "8.27.0",
80-
"@typescript-eslint/rule-tester": "8.27.0",
79+
"@typescript-eslint/rule-schema-to-typescript-types": "8.28.0",
80+
"@typescript-eslint/rule-tester": "8.28.0",
8181
"ajv": "^6.12.6",
8282
"cross-env": "^7.0.3",
8383
"cross-fetch": "*",

Diff for: packages/eslint-plugin/src/rules/consistent-type-exports.ts

+4-6
Original file line numberDiff line numberDiff line change
@@ -203,13 +203,11 @@ export default createRule<Options, MessageIds>({
203203
// Cache the first encountered exports for the package. We will need to come
204204
// back to these later when fixing the problems.
205205
if (node.exportKind === 'type') {
206-
if (sourceExports.typeOnlyNamedExport == null) {
207-
// The export is a type export
208-
sourceExports.typeOnlyNamedExport = node;
209-
}
210-
} else if (sourceExports.valueOnlyNamedExport == null) {
206+
// The export is a type export
207+
sourceExports.typeOnlyNamedExport ??= node;
208+
} else {
211209
// The export is a value export
212-
sourceExports.valueOnlyNamedExport = node;
210+
sourceExports.valueOnlyNamedExport ??= node;
213211
}
214212

215213
// Next for the current export, we will separate type/value specifiers.

Diff for: packages/eslint-plugin/src/rules/no-unnecessary-condition.ts

+12-8
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ export default createRule<Options, MessageId>({
357357
// Since typescript array index signature types don't represent the
358358
// possibility of out-of-bounds access, if we're indexing into an array
359359
// just skip the check, to avoid false positives
360-
if (isArrayIndexExpression(expression)) {
360+
if (!isNoUncheckedIndexedAccess && isArrayIndexExpression(expression)) {
361361
return;
362362
}
363363

@@ -424,12 +424,13 @@ export default createRule<Options, MessageId>({
424424
// possibility of out-of-bounds access, if we're indexing into an array
425425
// just skip the check, to avoid false positives
426426
if (
427-
!isArrayIndexExpression(node) &&
428-
!(
429-
node.type === AST_NODE_TYPES.ChainExpression &&
430-
node.expression.type !== AST_NODE_TYPES.TSNonNullExpression &&
431-
optionChainContainsOptionArrayIndex(node.expression)
432-
)
427+
isNoUncheckedIndexedAccess ||
428+
(!isArrayIndexExpression(node) &&
429+
!(
430+
node.type === AST_NODE_TYPES.ChainExpression &&
431+
node.expression.type !== AST_NODE_TYPES.TSNonNullExpression &&
432+
optionChainContainsOptionArrayIndex(node.expression)
433+
))
433434
) {
434435
messageId = 'neverNullish';
435436
}
@@ -835,7 +836,10 @@ export default createRule<Options, MessageId>({
835836
// Since typescript array index signature types don't represent the
836837
// possibility of out-of-bounds access, if we're indexing into an array
837838
// just skip the check, to avoid false positives
838-
if (optionChainContainsOptionArrayIndex(node)) {
839+
if (
840+
!isNoUncheckedIndexedAccess &&
841+
optionChainContainsOptionArrayIndex(node)
842+
) {
839843
return;
840844
}
841845

Diff for: packages/eslint-plugin/src/rules/no-unsafe-function-type.ts

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ export default createRule({
1212
description: 'Disallow using the unsafe built-in Function type',
1313
recommended: 'recommended',
1414
},
15-
fixable: 'code',
1615
messages: {
1716
bannedFunctionType: [
1817
'The `Function` type accepts any function-like value.',

Diff for: packages/eslint-plugin/src/rules/no-unsafe-return.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,7 @@ export default createRule({
8080
ts.isArrowFunction(functionTSNode)
8181
? getContextualType(checker, functionTSNode)
8282
: services.getTypeAtLocation(functionNode);
83-
if (!functionType) {
84-
functionType = services.getTypeAtLocation(functionNode);
85-
}
83+
functionType ??= services.getTypeAtLocation(functionNode);
8684
const callSignatures = tsutils.getCallSignaturesOfType(functionType);
8785
// If there is an explicit type annotation *and* that type matches the actual
8886
// function return type, we shouldn't complain (it's intentional, even if unsafe)

0 commit comments

Comments
 (0)