From b22baca7087449a0a4aa8e0247789954067da168 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Wed, 25 Oct 2023 11:19:12 +0300 Subject: [PATCH 1/3] chore: fix miscellaneous no-unnecessary-condition violations --- .../ast-spec/tests/util/serializers/Node.ts | 2 ++ .../src/rules/no-poorly-typed-ts-props.ts | 9 -------- .../src/rules/plugin-test-formatting.ts | 1 + .../src/rules/prefer-ast-types-enum.ts | 4 ++-- .../eslint-plugin-tslint/src/rules/config.ts | 2 +- .../src/generateArrayType.ts | 6 +----- packages/rule-tester/src/RuleTester.ts | 2 ++ .../rule-tester/src/utils/config-validator.ts | 8 ++++--- .../src/utils/getRuleOptionsSchema.ts | 4 +++- packages/rule-tester/src/utils/interpolate.ts | 2 +- .../src/referencer/ClassVisitor.ts | 14 ++----------- .../src/referencer/PatternVisitor.ts | 5 ++--- .../src/referencer/Referencer.ts | 1 + .../src/referencer/TypeVisitor.ts | 7 ++++--- .../scope-manager/src/scope/GlobalScope.ts | 2 +- packages/scope-manager/src/scope/ScopeBase.ts | 21 ++++++------------- .../tests/types/reference-type.test.ts | 8 +++---- packages/type-utils/src/getContextualType.ts | 3 --- .../type-utils/src/getSourceFileOfNode.ts | 2 +- packages/type-utils/src/getTypeArguments.ts | 13 ------------ packages/type-utils/src/index.ts | 1 - packages/type-utils/src/isTypeReadonly.ts | 5 +---- packages/type-utils/src/predicates.ts | 11 ++-------- .../src/eslint-utils/getParserServices.ts | 1 + 24 files changed, 43 insertions(+), 91 deletions(-) delete mode 100644 packages/type-utils/src/getTypeArguments.ts diff --git a/packages/ast-spec/tests/util/serializers/Node.ts b/packages/ast-spec/tests/util/serializers/Node.ts index bd6a9536ba76..fc77e55cff6a 100644 --- a/packages/ast-spec/tests/util/serializers/Node.ts +++ b/packages/ast-spec/tests/util/serializers/Node.ts @@ -56,6 +56,8 @@ const serializer: NewPlugin = { for (const key of keys) { const value = node[key]; + // Filter out undefined values, as they're not in our known accepted shapes + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (value === undefined) { continue; } diff --git a/packages/eslint-plugin-internal/src/rules/no-poorly-typed-ts-props.ts b/packages/eslint-plugin-internal/src/rules/no-poorly-typed-ts-props.ts index 7b34aa0fd260..1d07e54351b4 100644 --- a/packages/eslint-plugin-internal/src/rules/no-poorly-typed-ts-props.ts +++ b/packages/eslint-plugin-internal/src/rules/no-poorly-typed-ts-props.ts @@ -11,11 +11,6 @@ This rule simply warns against using them, as using them will likely introduce t */ const BANNED_PROPERTIES = [ - // { - // type: 'Node', - // property: 'parent', - // fixWith: null, - // }, { type: 'Symbol', property: 'declarations', @@ -87,10 +82,6 @@ export default createRule({ messageId: 'suggestedFix', data: banned, fix(fixer): TSESLint.RuleFix | null { - if (banned.fixWith == null) { - return null; - } - return fixer.replaceText(node.property, banned.fixWith); }, }, diff --git a/packages/eslint-plugin-internal/src/rules/plugin-test-formatting.ts b/packages/eslint-plugin-internal/src/rules/plugin-test-formatting.ts index f55b9e96950c..6677327d6a2b 100644 --- a/packages/eslint-plugin-internal/src/rules/plugin-test-formatting.ts +++ b/packages/eslint-plugin-internal/src/rules/plugin-test-formatting.ts @@ -171,6 +171,7 @@ export default createRule({ } catch (ex) { // ex instanceof Error is false as of @prettier/sync@0.3.0, as is ex instanceof SyntaxError if ( + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition (ex as Partial | undefined)?.constructor?.name !== 'SyntaxError' ) { diff --git a/packages/eslint-plugin-internal/src/rules/prefer-ast-types-enum.ts b/packages/eslint-plugin-internal/src/rules/prefer-ast-types-enum.ts index e042f328614e..9e97e44d2536 100755 --- a/packages/eslint-plugin-internal/src/rules/prefer-ast-types-enum.ts +++ b/packages/eslint-plugin-internal/src/rules/prefer-ast-types-enum.ts @@ -40,8 +40,8 @@ export default createRule({ return { Literal(node: TSESTree.Literal): void { if ( - node.parent?.type === AST_NODE_TYPES.TSEnumMember && - node.parent.parent?.type === AST_NODE_TYPES.TSEnumDeclaration && + node.parent.type === AST_NODE_TYPES.TSEnumMember && + node.parent.parent.type === AST_NODE_TYPES.TSEnumDeclaration && ['AST_NODE_TYPES', 'AST_TOKEN_TYPES', 'DefinitionType'].includes( node.parent.parent.id.name, ) diff --git a/packages/eslint-plugin-tslint/src/rules/config.ts b/packages/eslint-plugin-tslint/src/rules/config.ts index 23b7558b80fb..2cb602917688 100644 --- a/packages/eslint-plugin-tslint/src/rules/config.ts +++ b/packages/eslint-plugin-tslint/src/rules/config.ts @@ -146,7 +146,7 @@ export default createRule({ /** * Format the TSLint results for ESLint */ - if (result.failures?.length) { + if (result.failures.length) { result.failures.forEach(failure => { const start = failure.getStartPosition().getLineAndCharacter(); const end = failure.getEndPosition().getLineAndCharacter(); diff --git a/packages/rule-schema-to-typescript-types/src/generateArrayType.ts b/packages/rule-schema-to-typescript-types/src/generateArrayType.ts index 3efe5ed0af1b..f8a551c61092 100644 --- a/packages/rule-schema-to-typescript-types/src/generateArrayType.ts +++ b/packages/rule-schema-to-typescript-types/src/generateArrayType.ts @@ -24,11 +24,7 @@ export function generateArrayType( // but that's obviously dumb and loose so let's not even bother with it throw new UnexpectedError('Unexpected missing items', schema); } - if ( - schema.items && - !TSUtils.isArray(schema.items) && - schema.additionalItems - ) { + if (!TSUtils.isArray(schema.items) && schema.additionalItems) { throw new NotSupportedError( 'singlely-typed array with additionalItems', schema, diff --git a/packages/rule-tester/src/RuleTester.ts b/packages/rule-tester/src/RuleTester.ts index 85bd223d8609..ed639c234938 100644 --- a/packages/rule-tester/src/RuleTester.ts +++ b/packages/rule-tester/src/RuleTester.ts @@ -1,3 +1,5 @@ +// Many of the checks in this file are against untrusted user inputs +/* eslint-disable @typescript-eslint/no-unnecessary-condition */ // Forked from https://github.com/eslint/eslint/blob/ad9dd6a933fd098a0d99c6a9aa059850535c23ee/lib/rule-tester/rule-tester.js import assert from 'node:assert'; diff --git a/packages/rule-tester/src/utils/config-validator.ts b/packages/rule-tester/src/utils/config-validator.ts index 34b65987444c..d3690bc9ba17 100644 --- a/packages/rule-tester/src/utils/config-validator.ts +++ b/packages/rule-tester/src/utils/config-validator.ts @@ -24,7 +24,7 @@ const { ConfigOps, environments: BuiltInEnvironments } = Legacy; const ajv = ajvBuilder(); const ruleValidators = new WeakMap(); -let validateSchema: ValidateFunction; +let validateSchema: ValidateFunction | undefined; const severityMap = { error: 2, warn: 1, @@ -40,8 +40,10 @@ function validateRuleSeverity(options: Linter.RuleEntry): number | string { const severity = Array.isArray(options) ? options[0] : options; const normSeverity = typeof severity === 'string' - ? severityMap[severity.toLowerCase() as Linter.SeverityString] - : severity; + ? (severityMap[severity.toLowerCase() as Linter.SeverityString] as + | number + | undefined) + : (severity as number); if (normSeverity === 0 || normSeverity === 1 || normSeverity === 2) { return normSeverity; diff --git a/packages/rule-tester/src/utils/getRuleOptionsSchema.ts b/packages/rule-tester/src/utils/getRuleOptionsSchema.ts index 51f94711f701..1ff81d658e8e 100644 --- a/packages/rule-tester/src/utils/getRuleOptionsSchema.ts +++ b/packages/rule-tester/src/utils/getRuleOptionsSchema.ts @@ -10,7 +10,9 @@ import { isReadonlyArray } from './isReadonlyArray'; * @param rule A new-style rule object * @returns JSON Schema for the rule's options. */ -export function getRuleOptionsSchema(rule: AnyRuleModule): JSONSchema4 | null { +export function getRuleOptionsSchema( + rule: Partial, +): JSONSchema4 | null { const schema = rule.meta?.schema; // Given a tuple of schemas, insert warning level at the beginning diff --git a/packages/rule-tester/src/utils/interpolate.ts b/packages/rule-tester/src/utils/interpolate.ts index 0b3266fefb9b..53e5aa351938 100644 --- a/packages/rule-tester/src/utils/interpolate.ts +++ b/packages/rule-tester/src/utils/interpolate.ts @@ -4,7 +4,7 @@ import type { ReportDescriptorMessageData } from '@typescript-eslint/utils/ts-es export function interpolate( text: string, - data: ReportDescriptorMessageData, + data: ReportDescriptorMessageData | undefined, ): string { if (!data) { return text; diff --git a/packages/scope-manager/src/referencer/ClassVisitor.ts b/packages/scope-manager/src/referencer/ClassVisitor.ts index b22cc27133c6..33b48c7a103b 100644 --- a/packages/scope-manager/src/referencer/ClassVisitor.ts +++ b/packages/scope-manager/src/referencer/ClassVisitor.ts @@ -75,7 +75,7 @@ class ClassVisitor extends Visitor { this.visitType(node.typeParameters); // then the usages this.visitType(node.superTypeArguments); - node.implements?.forEach(imp => this.visitType(imp)); + node.implements.forEach(imp => this.visitType(imp)); this.visit(node.body); @@ -224,17 +224,7 @@ class ClassVisitor extends Visitor { this.visitMetadataType(node.returnType, withMethodDecorators); this.visitType(node.typeParameters); - // In TypeScript there are a number of function-like constructs which have no body, - // so check it exists before traversing - if (node.body) { - // Skip BlockStatement to prevent creating BlockStatement scope. - if (node.body.type === AST_NODE_TYPES.BlockStatement) { - this.#referencer.visitChildren(node.body); - } else { - this.#referencer.visit(node.body); - } - } - + this.#referencer.visitChildren(node.body); this.#referencer.close(node); } diff --git a/packages/scope-manager/src/referencer/PatternVisitor.ts b/packages/scope-manager/src/referencer/PatternVisitor.ts index 6e1140e18959..51564882ef88 100644 --- a/packages/scope-manager/src/referencer/PatternVisitor.ts +++ b/packages/scope-manager/src/referencer/PatternVisitor.ts @@ -92,12 +92,11 @@ class PatternVisitor extends VisitorBase { } protected Identifier(pattern: TSESTree.Identifier): void { - const lastRestElement = - this.#restElements[this.#restElements.length - 1] ?? null; + const lastRestElement = this.#restElements.at(-1); this.#callback(pattern, { topLevel: pattern === this.#rootPattern, - rest: lastRestElement != null && lastRestElement.argument === pattern, + rest: lastRestElement?.argument === pattern, assignments: this.#assignments, }); } diff --git a/packages/scope-manager/src/referencer/Referencer.ts b/packages/scope-manager/src/referencer/Referencer.ts index 38e4a0d2adac..f5d36f2fa0ba 100644 --- a/packages/scope-manager/src/referencer/Referencer.ts +++ b/packages/scope-manager/src/referencer/Referencer.ts @@ -88,6 +88,7 @@ class Referencer extends Visitor { private populateGlobalsFromLib(globalScope: GlobalScope): void { for (const lib of this.#lib) { const variables = TSLibraries[lib]; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition /* istanbul ignore if */ if (!variables) { throw new Error(`Invalid value for lib provided: ${lib}`); } diff --git a/packages/scope-manager/src/referencer/TypeVisitor.ts b/packages/scope-manager/src/referencer/TypeVisitor.ts index 9daa2e64093a..786b1059b5a1 100644 --- a/packages/scope-manager/src/referencer/TypeVisitor.ts +++ b/packages/scope-manager/src/referencer/TypeVisitor.ts @@ -2,7 +2,7 @@ import type { TSESTree } from '@typescript-eslint/types'; import { AST_NODE_TYPES } from '@typescript-eslint/types'; import { ParameterDefinition, TypeDefinition } from '../definition'; -import { ScopeType } from '../scope'; +import { type Scope, ScopeType } from '../scope'; import type { Referencer } from './Referencer'; import { Visitor } from './Visitor'; @@ -53,6 +53,7 @@ class TypeVisitor extends Visitor { }); // there are a few special cases where the type annotation is owned by the parameter, not the pattern + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!didVisitAnnotation && 'typeAnnotation' in param) { this.visit(param.typeAnnotation); } @@ -147,7 +148,7 @@ class TypeVisitor extends Visitor { scope.type === ScopeType.mappedType ) { // search up the scope tree to figure out if we're in a nested type scope - let currentScope = scope.upper; + let currentScope = scope.upper as Scope | undefined; while (currentScope) { if ( currentScope.type === ScopeType.functionType || @@ -186,7 +187,7 @@ class TypeVisitor extends Visitor { this.visit(node.typeParameters); } - node.extends?.forEach(this.visit, this); + node.extends.forEach(this.visit, this); this.visit(node.body); if (node.typeParameters) { diff --git a/packages/scope-manager/src/scope/GlobalScope.ts b/packages/scope-manager/src/scope/GlobalScope.ts index de253e5543d6..6bf32a12f536 100644 --- a/packages/scope-manager/src/scope/GlobalScope.ts +++ b/packages/scope-manager/src/scope/GlobalScope.ts @@ -60,7 +60,7 @@ class GlobalScope extends ScopeBase< // create an implicit global variable from assignment expression const info = ref.maybeImplicitGlobal; const node = info.pattern; - if (node && node.type === AST_NODE_TYPES.Identifier) { + if (node.type === AST_NODE_TYPES.Identifier) { this.defineVariable( node.name, this.implicit.set, diff --git a/packages/scope-manager/src/scope/ScopeBase.ts b/packages/scope-manager/src/scope/ScopeBase.ts index 81c712dff389..1cdb2c98586c 100644 --- a/packages/scope-manager/src/scope/ScopeBase.ts +++ b/packages/scope-manager/src/scope/ScopeBase.ts @@ -232,7 +232,7 @@ abstract class ScopeBase< block: TBlock, isMethodDefinition: boolean, ) { - const upperScopeAsScopeBase = upperScope!; + const upperScopeAsScopeBase = upperScope; this.type = type; this.#dynamic = @@ -240,7 +240,7 @@ abstract class ScopeBase< this.block = block; this.variableScope = this.isVariableScope() ? this - : upperScopeAsScopeBase.variableScope; + : upperScopeAsScopeBase!.variableScope; this.upper = upperScope; /** @@ -249,10 +249,8 @@ abstract class ScopeBase< */ this.isStrict = isStrictScope(this as Scope, block, isMethodDefinition); - if (upperScopeAsScopeBase) { - // this is guaranteed to be correct at runtime - upperScopeAsScopeBase.childScopes.push(this as Scope); - } + // this is guaranteed to be correct at runtime + upperScopeAsScopeBase?.childScopes.push(this as Scope); this.#declaredVariables = scopeManager.declaredVariables; @@ -293,11 +291,7 @@ abstract class ScopeBase< return ( defs.length > 0 && defs.every(def => { - if ( - def.type === DefinitionType.Variable && - def.parent?.type === AST_NODE_TYPES.VariableDeclaration && - def.parent.kind === 'var' - ) { + if (def.type === DefinitionType.Variable && def.parent.kind === 'var') { return false; } return true; @@ -386,10 +380,7 @@ abstract class ScopeBase< } protected delegateToUpperScope(ref: Reference): void { - const upper = this.upper! as AnyScope; - if (upper?.leftToResolve) { - upper.leftToResolve.push(ref); - } + (this.upper as AnyScope | undefined)?.leftToResolve?.push(ref); this.through.push(ref); } diff --git a/packages/scope-manager/tests/types/reference-type.test.ts b/packages/scope-manager/tests/types/reference-type.test.ts index 1ede0488440d..79825f2e9aa6 100644 --- a/packages/scope-manager/tests/types/reference-type.test.ts +++ b/packages/scope-manager/tests/types/reference-type.test.ts @@ -21,7 +21,7 @@ describe('referencing a type - positive', () => { AST_NODE_TYPES.TSTypeAliasDeclaration, n => n.id.name === 'OtherType', ); - expect(variable.references[0].identifier.parent?.parent).toBe( + expect(variable.references[0].identifier.parent.parent).toBe( referencingNode, ); }); @@ -39,7 +39,7 @@ describe('referencing a type - positive', () => { ast, AST_NODE_TYPES.TSTypeAliasDeclaration, ); - expect(variable.references[0].identifier.parent?.parent).toBe( + expect(variable.references[0].identifier.parent.parent).toBe( referencingNode, ); }); @@ -87,7 +87,7 @@ describe('referencing a type - positive', () => { AST_NODE_TYPES.TSTypeAliasDeclaration, n => n.id.name === 'reference1', ); - expect(variable.references[1].identifier.parent?.parent).toBe( + expect(variable.references[1].identifier.parent.parent).toBe( referencingTypeNode, ); // third ref is the variable reference @@ -141,7 +141,7 @@ describe('referencing a type - positive', () => { ast, AST_NODE_TYPES.TSTypeAliasDeclaration, ); - expect(variable.references[1].identifier.parent?.parent).toBe( + expect(variable.references[1].identifier.parent.parent).toBe( referencingNode, ); }); diff --git a/packages/type-utils/src/getContextualType.ts b/packages/type-utils/src/getContextualType.ts index e201874b03a6..8aee05fcb55d 100644 --- a/packages/type-utils/src/getContextualType.ts +++ b/packages/type-utils/src/getContextualType.ts @@ -10,9 +10,6 @@ export function getContextualType( node: ts.Expression, ): ts.Type | undefined { const parent = node.parent; - if (!parent) { - return; - } if (ts.isCallExpression(parent) || ts.isNewExpression(parent)) { if (node === parent.expression) { diff --git a/packages/type-utils/src/getSourceFileOfNode.ts b/packages/type-utils/src/getSourceFileOfNode.ts index 9bd8f77ea464..18e7ca27ecde 100644 --- a/packages/type-utils/src/getSourceFileOfNode.ts +++ b/packages/type-utils/src/getSourceFileOfNode.ts @@ -4,7 +4,7 @@ import * as ts from 'typescript'; * Gets the source file for a given node */ export function getSourceFileOfNode(node: ts.Node): ts.SourceFile { - while (node && node.kind !== ts.SyntaxKind.SourceFile) { + while (node.kind !== ts.SyntaxKind.SourceFile) { node = node.parent; } return node as ts.SourceFile; diff --git a/packages/type-utils/src/getTypeArguments.ts b/packages/type-utils/src/getTypeArguments.ts deleted file mode 100644 index 04187cea5afc..000000000000 --- a/packages/type-utils/src/getTypeArguments.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type * as ts from 'typescript'; - -export function getTypeArguments( - type: ts.TypeReference, - checker: ts.TypeChecker, -): readonly ts.Type[] { - // getTypeArguments was only added in TS3.7 - if (checker.getTypeArguments) { - return checker.getTypeArguments(type); - } - - return type.typeArguments ?? []; -} diff --git a/packages/type-utils/src/index.ts b/packages/type-utils/src/index.ts index 9fc499aa8f31..6a8d5c1c554d 100644 --- a/packages/type-utils/src/index.ts +++ b/packages/type-utils/src/index.ts @@ -4,7 +4,6 @@ export * from './getContextualType'; export * from './getDeclaration'; export * from './getSourceFileOfNode'; export * from './getTokenAtPosition'; -export * from './getTypeArguments'; export * from './getTypeName'; export * from './isTypeReadonly'; export * from './isUnsafeAssignment'; diff --git a/packages/type-utils/src/isTypeReadonly.ts b/packages/type-utils/src/isTypeReadonly.ts index 8cfee5272b14..6362adc500b4 100644 --- a/packages/type-utils/src/isTypeReadonly.ts +++ b/packages/type-utils/src/isTypeReadonly.ts @@ -3,7 +3,6 @@ import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import { getTypeArguments } from './getTypeArguments'; import { getTypeOfPropertyOfType } from './propertyTypes'; import type { TypeOrValueSpecifier } from './TypeOrValueSpecifier'; import { @@ -56,9 +55,7 @@ function isTypeReadonlyArrayOrTuple( ): Readonlyness { const checker = program.getTypeChecker(); function checkTypeArguments(arrayType: ts.TypeReference): Readonlyness { - const typeArguments = - // getTypeArguments was only added in TS3.7 - getTypeArguments(arrayType, checker); + const typeArguments = checker.getTypeArguments(arrayType); // this shouldn't happen in reality as: // - tuples require at least 1 type argument diff --git a/packages/type-utils/src/predicates.ts b/packages/type-utils/src/predicates.ts index 7bdae284ecce..fdc79dc45ac0 100644 --- a/packages/type-utils/src/predicates.ts +++ b/packages/type-utils/src/predicates.ts @@ -2,7 +2,6 @@ import debug from 'debug'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import { getTypeArguments } from './getTypeArguments'; import { getTypeFlags, isTypeFlagSet } from './typeFlagUtils'; const log = debug('typescript-eslint:eslint-plugin:utils:types'); @@ -101,10 +100,7 @@ export function isTypeAnyArrayType( ): boolean { return ( checker.isArrayType(type) && - isTypeAnyType( - // getTypeArguments was only added in TS3.7 - getTypeArguments(type, checker)[0], - ) + isTypeAnyType(checker.getTypeArguments(type)[0]) ); } @@ -117,10 +113,7 @@ export function isTypeUnknownArrayType( ): boolean { return ( checker.isArrayType(type) && - isTypeUnknownType( - // getTypeArguments was only added in TS3.7 - getTypeArguments(type, checker)[0], - ) + isTypeUnknownType(checker.getTypeArguments(type)[0]) ); } diff --git a/packages/utils/src/eslint-utils/getParserServices.ts b/packages/utils/src/eslint-utils/getParserServices.ts index 6b4d50b88638..ef6d00e0ae6a 100644 --- a/packages/utils/src/eslint-utils/getParserServices.ts +++ b/packages/utils/src/eslint-utils/getParserServices.ts @@ -68,6 +68,7 @@ function getParserServices( // error message explaining the problem. if ( context.parserServices?.esTreeNodeToTSNodeMap == null || + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition context.parserServices.tsNodeToESTreeNodeMap == null ) { throw new Error(ERROR_MESSAGE); From 412dbe5bb0c85dc36094ddee2ecec9e349f6b2f5 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Wed, 25 Oct 2023 15:13:39 +0300 Subject: [PATCH 2/3] Fixed references to deleted getTypeArguments function, and unused disables --- packages/ast-spec/tests/util/serializers/Node.ts | 2 -- .../src/rules/plugin-test-formatting.ts | 1 - .../eslint-plugin/src/rules/no-misused-promises.ts | 6 +++--- .../src/rules/no-unnecessary-type-arguments.ts | 3 +-- .../eslint-plugin/src/rules/no-unsafe-argument.ts | 11 ++++------- .../eslint-plugin/src/rules/no-unsafe-assignment.ts | 3 +-- .../src/rules/require-array-sort-compare.ts | 3 +-- packages/rule-tester/src/RuleTester.ts | 2 -- packages/scope-manager/src/referencer/Referencer.ts | 1 - packages/scope-manager/src/referencer/TypeVisitor.ts | 1 - packages/utils/src/eslint-utils/getParserServices.ts | 1 - 11 files changed, 10 insertions(+), 24 deletions(-) diff --git a/packages/ast-spec/tests/util/serializers/Node.ts b/packages/ast-spec/tests/util/serializers/Node.ts index fc77e55cff6a..bd6a9536ba76 100644 --- a/packages/ast-spec/tests/util/serializers/Node.ts +++ b/packages/ast-spec/tests/util/serializers/Node.ts @@ -56,8 +56,6 @@ const serializer: NewPlugin = { for (const key of keys) { const value = node[key]; - // Filter out undefined values, as they're not in our known accepted shapes - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (value === undefined) { continue; } diff --git a/packages/eslint-plugin-internal/src/rules/plugin-test-formatting.ts b/packages/eslint-plugin-internal/src/rules/plugin-test-formatting.ts index 6677327d6a2b..f55b9e96950c 100644 --- a/packages/eslint-plugin-internal/src/rules/plugin-test-formatting.ts +++ b/packages/eslint-plugin-internal/src/rules/plugin-test-formatting.ts @@ -171,7 +171,6 @@ export default createRule({ } catch (ex) { // ex instanceof Error is false as of @prettier/sync@0.3.0, as is ex instanceof SyntaxError if ( - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition (ex as Partial | undefined)?.constructor?.name !== 'SyntaxError' ) { diff --git a/packages/eslint-plugin/src/rules/no-misused-promises.ts b/packages/eslint-plugin/src/rules/no-misused-promises.ts index 7fd6fb9ca71c..fa5f9ae5796b 100644 --- a/packages/eslint-plugin/src/rules/no-misused-promises.ts +++ b/packages/eslint-plugin/src/rules/no-misused-promises.ts @@ -3,7 +3,7 @@ import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import { createRule, getParserServices, getTypeArguments } from '../util'; +import { createRule, getParserServices } from '../util'; type Options = [ { @@ -556,7 +556,7 @@ function voidFunctionArguments( // Unwrap 'Array' to 'MaybeVoidFunction', // so that we'll handle it in the same way as a non-rest // 'param: MaybeVoidFunction' - type = getTypeArguments(type, checker)[0]; + type = checker.getTypeArguments(type)[0]; for (let i = index; i < node.arguments.length; i++) { checkThenableOrVoidArgument( checker, @@ -570,7 +570,7 @@ function voidFunctionArguments( } else if (checker.isTupleType(type)) { // Check each type in the tuple - for example, [boolean, () => void] would // add the index of the second tuple parameter to 'voidReturnIndices' - const typeArgs = getTypeArguments(type, checker); + const typeArgs = checker.getTypeArguments(type); for ( let i = index; i < node.arguments.length && i - index < typeArgs.length; diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts b/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts index d766257d6c6c..356e39af93ff 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts @@ -6,7 +6,6 @@ import { createRule, findFirstResult, getParserServices, - getTypeArguments, isTypeReferenceType, } from '../util'; @@ -51,7 +50,7 @@ export default createRule<[], MessageIds>({ if (isTypeReferenceType(type)) { return { type: type.target, - typeArguments: getTypeArguments(type, checker), + typeArguments: checker.getTypeArguments(type), }; } return { diff --git a/packages/eslint-plugin/src/rules/no-unsafe-argument.ts b/packages/eslint-plugin/src/rules/no-unsafe-argument.ts index fe74d1360969..a04440f383c3 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-argument.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-argument.ts @@ -5,7 +5,6 @@ import * as ts from 'typescript'; import { createRule, getParserServices, - getTypeArguments, isTypeAnyArrayType, isTypeAnyType, isUnsafeAssignment, @@ -64,13 +63,13 @@ class FunctionSignature { // is a rest param if (checker.isArrayType(type)) { restType = { - type: getTypeArguments(type, checker)[0], + type: checker.getTypeArguments(type)[0], kind: RestTypeKind.Array, index: i, }; } else if (checker.isTupleType(type)) { restType = { - typeArguments: getTypeArguments(type, checker), + typeArguments: checker.getTypeArguments(type), kind: RestTypeKind.Tuple, index: i, }; @@ -205,10 +204,8 @@ export default createRule<[], MessageIds>({ }); } else if (checker.isTupleType(spreadArgType)) { // foo(...[tuple1, tuple2]) - const spreadTypeArguments = getTypeArguments( - spreadArgType, - checker, - ); + const spreadTypeArguments = + checker.getTypeArguments(spreadArgType); for (const tupleType of spreadTypeArguments) { const parameterType = signature.getNextParameterType(); if (parameterType == null) { diff --git a/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts b/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts index c16a4904756b..4ce2f6db99a3 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts @@ -9,7 +9,6 @@ import { getContextualType, getParserServices, getThisExpression, - getTypeArguments, isTypeAnyArrayType, isTypeAnyType, isTypeUnknownType, @@ -97,7 +96,7 @@ export default createRule({ return true; } - const tupleElements = getTypeArguments(senderType, checker); + const tupleElements = checker.getTypeArguments(senderType); // tuple with any // const [x] = [1 as any]; diff --git a/packages/eslint-plugin/src/rules/require-array-sort-compare.ts b/packages/eslint-plugin/src/rules/require-array-sort-compare.ts index 4097362bb247..1b2916ea0b48 100644 --- a/packages/eslint-plugin/src/rules/require-array-sort-compare.ts +++ b/packages/eslint-plugin/src/rules/require-array-sort-compare.ts @@ -4,7 +4,6 @@ import { createRule, getConstrainedTypeAtLocation, getParserServices, - getTypeArguments, getTypeName, isTypeArrayTypeOrUnionOfArrayTypes, } from '../util'; @@ -61,7 +60,7 @@ export default createRule({ const type = services.getTypeAtLocation(node); if (checker.isArrayType(type) || checker.isTupleType(type)) { - const typeArgs = getTypeArguments(type, checker); + const typeArgs = checker.getTypeArguments(type); return typeArgs.every(arg => getTypeName(checker, arg) === 'string'); } return false; diff --git a/packages/rule-tester/src/RuleTester.ts b/packages/rule-tester/src/RuleTester.ts index ed639c234938..85bd223d8609 100644 --- a/packages/rule-tester/src/RuleTester.ts +++ b/packages/rule-tester/src/RuleTester.ts @@ -1,5 +1,3 @@ -// Many of the checks in this file are against untrusted user inputs -/* eslint-disable @typescript-eslint/no-unnecessary-condition */ // Forked from https://github.com/eslint/eslint/blob/ad9dd6a933fd098a0d99c6a9aa059850535c23ee/lib/rule-tester/rule-tester.js import assert from 'node:assert'; diff --git a/packages/scope-manager/src/referencer/Referencer.ts b/packages/scope-manager/src/referencer/Referencer.ts index f5d36f2fa0ba..38e4a0d2adac 100644 --- a/packages/scope-manager/src/referencer/Referencer.ts +++ b/packages/scope-manager/src/referencer/Referencer.ts @@ -88,7 +88,6 @@ class Referencer extends Visitor { private populateGlobalsFromLib(globalScope: GlobalScope): void { for (const lib of this.#lib) { const variables = TSLibraries[lib]; - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition /* istanbul ignore if */ if (!variables) { throw new Error(`Invalid value for lib provided: ${lib}`); } diff --git a/packages/scope-manager/src/referencer/TypeVisitor.ts b/packages/scope-manager/src/referencer/TypeVisitor.ts index 786b1059b5a1..2bb922be4023 100644 --- a/packages/scope-manager/src/referencer/TypeVisitor.ts +++ b/packages/scope-manager/src/referencer/TypeVisitor.ts @@ -53,7 +53,6 @@ class TypeVisitor extends Visitor { }); // there are a few special cases where the type annotation is owned by the parameter, not the pattern - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!didVisitAnnotation && 'typeAnnotation' in param) { this.visit(param.typeAnnotation); } diff --git a/packages/utils/src/eslint-utils/getParserServices.ts b/packages/utils/src/eslint-utils/getParserServices.ts index ef6d00e0ae6a..6b4d50b88638 100644 --- a/packages/utils/src/eslint-utils/getParserServices.ts +++ b/packages/utils/src/eslint-utils/getParserServices.ts @@ -68,7 +68,6 @@ function getParserServices( // error message explaining the problem. if ( context.parserServices?.esTreeNodeToTSNodeMap == null || - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition context.parserServices.tsNodeToESTreeNodeMap == null ) { throw new Error(ERROR_MESSAGE); From 97d62f272fdc0566c3264bcba3ef49c6151855dd Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 11 Nov 2023 15:52:21 -0500 Subject: [PATCH 3/3] Add getTypeArguments back, deprecated --- packages/type-utils/src/getTypeArguments.ts | 16 ++++++++++++++++ packages/type-utils/src/index.ts | 1 + 2 files changed, 17 insertions(+) create mode 100644 packages/type-utils/src/getTypeArguments.ts diff --git a/packages/type-utils/src/getTypeArguments.ts b/packages/type-utils/src/getTypeArguments.ts new file mode 100644 index 000000000000..06b85cead688 --- /dev/null +++ b/packages/type-utils/src/getTypeArguments.ts @@ -0,0 +1,16 @@ +import type * as ts from 'typescript'; + +/** + * @deprecated This is in TypeScript as of 3.7. + */ +export function getTypeArguments( + type: ts.TypeReference, + checker: ts.TypeChecker, +): readonly ts.Type[] { + // getTypeArguments was only added in TS3.7 + if (checker.getTypeArguments) { + return checker.getTypeArguments(type); + } + + return type.typeArguments ?? []; +} diff --git a/packages/type-utils/src/index.ts b/packages/type-utils/src/index.ts index 6a8d5c1c554d..9fc499aa8f31 100644 --- a/packages/type-utils/src/index.ts +++ b/packages/type-utils/src/index.ts @@ -4,6 +4,7 @@ export * from './getContextualType'; export * from './getDeclaration'; export * from './getSourceFileOfNode'; export * from './getTokenAtPosition'; +export * from './getTypeArguments'; export * from './getTypeName'; export * from './isTypeReadonly'; export * from './isUnsafeAssignment';