Skip to content

Commit d569924

Browse files
authored
fix(eslint-plugin): [no-unnecessary-condition] fix false positive when checking indexed access types (#6452)
* add new tests * allow naked index access type to be a condition
1 parent a1b3f7b commit d569924

File tree

2 files changed

+77
-2
lines changed

2 files changed

+77
-2
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,13 +235,13 @@ export default createRule<Options, MessageId>({
235235
const type = getNodeType(node);
236236

237237
// Conditional is always necessary if it involves:
238-
// `any` or `unknown` or a naked type parameter
238+
// `any` or `unknown` or a naked type variable
239239
if (
240240
unionTypeParts(type).some(
241241
part =>
242242
isTypeAnyType(part) ||
243243
isTypeUnknownType(part) ||
244-
isTypeFlagSet(part, ts.TypeFlags.TypeParameter),
244+
isTypeFlagSet(part, ts.TypeFlags.TypeVariable),
245245
)
246246
) {
247247
return;

packages/eslint-plugin/tests/rules/no-unnecessary-condition.test.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,36 @@ type OptionalFoo = Foo | undefined;
549549
declare const foo: OptionalFoo;
550550
foo?.[1]?.length;
551551
`,
552+
// https://github.com/typescript-eslint/typescript-eslint/issues/6264
553+
`
554+
function get<Obj, Key extends keyof Obj>(obj: Obj, key: Key) {
555+
const value = obj[key];
556+
if (value) {
557+
return value;
558+
}
559+
throw new Error('BOOM!');
560+
}
561+
562+
get({ foo: null }, 'foo');
563+
`,
564+
{
565+
code: `
566+
function getElem(dict: Record<string, { foo: string }>, key: string) {
567+
if (dict[key]) {
568+
return dict[key].foo;
569+
} else {
570+
return '';
571+
}
572+
}
573+
`,
574+
parserOptions: {
575+
tsconfigRootDir: getFixturesRootDir(),
576+
project: './tsconfig.noUncheckedIndexedAccess.json',
577+
},
578+
dependencyConstraints: {
579+
typescript: '4.1',
580+
},
581+
},
552582
],
553583
invalid: [
554584
// Ensure that it's checking in all the right places
@@ -1601,5 +1631,50 @@ foo?.test.length;
16011631
},
16021632
],
16031633
},
1634+
{
1635+
code: `
1636+
function pick<Obj extends Record<string, 1 | 2 | 3>, Key extends keyof Obj>(
1637+
obj: Obj,
1638+
key: Key,
1639+
): Obj[Key] {
1640+
const k = obj[key];
1641+
if (obj[key]) {
1642+
return obj[key];
1643+
}
1644+
throw new Error('Boom!');
1645+
}
1646+
1647+
pick({ foo: 1, bar: 2 }, 'bar');
1648+
`,
1649+
errors: [
1650+
{
1651+
messageId: 'alwaysTruthy',
1652+
line: 7,
1653+
endLine: 7,
1654+
column: 7,
1655+
endColumn: 15,
1656+
},
1657+
],
1658+
},
1659+
{
1660+
code: `
1661+
function getElem(dict: Record<string, { foo: string }>, key: string) {
1662+
if (dict[key]) {
1663+
return dict[key].foo;
1664+
} else {
1665+
return '';
1666+
}
1667+
}
1668+
`,
1669+
errors: [
1670+
{
1671+
messageId: 'alwaysTruthy',
1672+
line: 3,
1673+
endLine: 3,
1674+
column: 7,
1675+
endColumn: 16,
1676+
},
1677+
],
1678+
},
16041679
],
16051680
});

0 commit comments

Comments
 (0)