@@ -261,12 +261,6 @@ export default createRule<Options, MessageId>({
261
261
}
262
262
263
263
function checkNodeForNullish ( node : TSESTree . Expression ) : void {
264
- // Since typescript array index signature types don't represent the
265
- // possibility of out-of-bounds access, if we're indexing into an array
266
- // just skip the check, to avoid false positives
267
- if ( isArrayIndexExpression ( node ) ) {
268
- return ;
269
- }
270
264
const type = getNodeType ( node ) ;
271
265
// Conditional is always necessary if it involves `any` or `unknown`
272
266
if ( isTypeAnyType ( type ) || isTypeUnknownType ( type ) ) {
@@ -277,7 +271,19 @@ export default createRule<Options, MessageId>({
277
271
if ( isTypeFlagSet ( type , ts . TypeFlags . Never ) ) {
278
272
messageId = 'never' ;
279
273
} else if ( ! isPossiblyNullish ( type ) ) {
280
- messageId = 'neverNullish' ;
274
+ // Since typescript array index signature types don't represent the
275
+ // possibility of out-of-bounds access, if we're indexing into an array
276
+ // just skip the check, to avoid false positives
277
+ if (
278
+ ! isArrayIndexExpression ( node ) &&
279
+ ! (
280
+ node . type === AST_NODE_TYPES . ChainExpression &&
281
+ node . expression . type !== AST_NODE_TYPES . TSNonNullExpression &&
282
+ optionChainContainsOptionArrayIndex ( node . expression )
283
+ )
284
+ ) {
285
+ messageId = 'neverNullish' ;
286
+ }
281
287
} else if ( isAlwaysNullish ( type ) ) {
282
288
messageId = 'alwaysNullish' ;
283
289
}
@@ -477,19 +483,19 @@ export default createRule<Options, MessageId>({
477
483
// ?.x // type is {y: "z"}
478
484
// ?.y // This access is considered "unnecessary" according to the types
479
485
// ```
480
- function optionChainContainsArrayIndex (
486
+ function optionChainContainsOptionArrayIndex (
481
487
node : TSESTree . MemberExpression | TSESTree . CallExpression ,
482
488
) : boolean {
483
489
const lhsNode =
484
490
node . type === AST_NODE_TYPES . CallExpression ? node . callee : node . object ;
485
- if ( isArrayIndexExpression ( lhsNode ) ) {
491
+ if ( node . optional && isArrayIndexExpression ( lhsNode ) ) {
486
492
return true ;
487
493
}
488
494
if (
489
495
lhsNode . type === AST_NODE_TYPES . MemberExpression ||
490
496
lhsNode . type === AST_NODE_TYPES . CallExpression
491
497
) {
492
- return optionChainContainsArrayIndex ( lhsNode ) ;
498
+ return optionChainContainsOptionArrayIndex ( lhsNode ) ;
493
499
}
494
500
return false ;
495
501
}
@@ -584,7 +590,7 @@ export default createRule<Options, MessageId>({
584
590
// Since typescript array index signature types don't represent the
585
591
// possibility of out-of-bounds access, if we're indexing into an array
586
592
// just skip the check, to avoid false positives
587
- if ( optionChainContainsArrayIndex ( node ) ) {
593
+ if ( optionChainContainsOptionArrayIndex ( node ) ) {
588
594
return ;
589
595
}
590
596
0 commit comments