From ecb57de5eb50511bed163f6e1b27e31b8577344e Mon Sep 17 00:00:00 2001 From: Rebecca Stevens Date: Sat, 8 Jul 2023 03:20:27 +1200 Subject: [PATCH] fix(type-utils): treat intrinsic types as if they are from lib and never match error types (#6869) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(type-utils): treat intrinsic types as if they are from lib and never match error types * Update packages/type-utils/tests/TypeOrValueSpecifier.test.ts * chore: bump ts-api-utils to 1.0.1 * refactor: use isIntrinsicErrorType --------- Co-authored-by: Josh Goldberg ✨ --- packages/eslint-plugin/package.json | 2 +- packages/type-utils/package.json | 2 +- .../type-utils/src/TypeOrValueSpecifier.ts | 26 ++++++++++++++++--- .../tests/TypeOrValueSpecifier.test.ts | 18 +++++++++++++ packages/typescript-estree/package.json | 2 +- yarn.lock | 8 +++--- 6 files changed, 48 insertions(+), 10 deletions(-) diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index dca9f33ff7a..dbf23659cea 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -67,7 +67,7 @@ "natural-compare-lite": "^1.4.0", "natural-compare": "^1.4.0", "semver": "^7.5.0", - "ts-api-utils": "^1.0.0" + "ts-api-utils": "^1.0.1" }, "devDependencies": { "@types/debug": "*", diff --git a/packages/type-utils/package.json b/packages/type-utils/package.json index 5f3a3e79ac0..9223a854022 100644 --- a/packages/type-utils/package.json +++ b/packages/type-utils/package.json @@ -48,7 +48,7 @@ "@typescript-eslint/typescript-estree": "5.61.0", "@typescript-eslint/utils": "5.61.0", "debug": "^4.3.4", - "ts-api-utils": "^1.0.0" + "ts-api-utils": "^1.0.1" }, "devDependencies": { "@typescript-eslint/parser": "5.61.0", diff --git a/packages/type-utils/src/TypeOrValueSpecifier.ts b/packages/type-utils/src/TypeOrValueSpecifier.ts index 5542bf7d602..12c7679349d 100644 --- a/packages/type-utils/src/TypeOrValueSpecifier.ts +++ b/packages/type-utils/src/TypeOrValueSpecifier.ts @@ -1,6 +1,7 @@ import { getCanonicalFileName } from '@typescript-eslint/typescript-estree'; import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema'; import path from 'path'; +import * as tsutils from 'ts-api-utils'; import type * as ts from 'typescript'; interface FileSpecifier { @@ -122,6 +123,9 @@ function specifierNameMatches(type: ts.Type, name: string[] | string): boolean { if (typeof name === 'string') { name = [name]; } + if (name.some(item => item === type.intrinsicName)) { + return true; + } const symbol = type.aliasSymbol ?? type.getSymbol(); if (symbol === undefined) { return false; @@ -163,11 +167,29 @@ function typeDeclaredInPackage( ); } +function typeDeclaredInLib( + declarationFiles: ts.SourceFile[], + program: ts.Program, +): boolean { + // Assertion: The type is not an error type. + + // Intrinsic type (i.e. string, number, boolean, etc) - Treat it as if it's from lib. + if (declarationFiles.length === 0) { + return true; + } + return declarationFiles.some(declaration => + program.isSourceFileDefaultLibrary(declaration), + ); +} + export function typeMatchesSpecifier( type: ts.Type, specifier: TypeOrValueSpecifier, program: ts.Program, ): boolean { + if (tsutils.isIntrinsicErrorType(type)) { + return false; + } if (typeof specifier === 'string') { return specifierNameMatches(type, specifier); } @@ -183,9 +205,7 @@ export function typeMatchesSpecifier( case 'file': return typeDeclaredInFile(specifier.path, declarationFiles, program); case 'lib': - return declarationFiles.some(declaration => - program.isSourceFileDefaultLibrary(declaration), - ); + return typeDeclaredInLib(declarationFiles, program); case 'package': return typeDeclaredInPackage(specifier.package, declarationFiles); } diff --git a/packages/type-utils/tests/TypeOrValueSpecifier.test.ts b/packages/type-utils/tests/TypeOrValueSpecifier.test.ts index 2b2f68926f1..8ddca54d3b3 100644 --- a/packages/type-utils/tests/TypeOrValueSpecifier.test.ts +++ b/packages/type-utils/tests/TypeOrValueSpecifier.test.ts @@ -269,6 +269,19 @@ describe('TypeOrValueSpecifier', () => { ['type Test = RegExp;', { from: 'lib', name: ['BigInt', 'Date'] }], ])("doesn't match a mismatched lib specifier: %s", runTestNegative); + it.each<[string, TypeOrValueSpecifier]>([ + ['type Test = string;', { from: 'lib', name: 'string' }], + ['type Test = string;', { from: 'lib', name: ['string', 'number'] }], + ])('matches a matching intrinsic type specifier: %s', runTestPositive); + + it.each<[string, TypeOrValueSpecifier]>([ + ['type Test = string;', { from: 'lib', name: 'number' }], + ['type Test = string;', { from: 'lib', name: ['number', 'boolean'] }], + ])( + "doesn't match a mismatched intrinsic type specifier: %s", + runTestNegative, + ); + it.each<[string, TypeOrValueSpecifier]>([ [ 'import type {Node} from "typescript"; type Test = Node;', @@ -405,5 +418,10 @@ describe('TypeOrValueSpecifier', () => { { from: 'package', name: ['RegExp', 'BigInt'], package: 'foo-package' }, ], ])("doesn't match a mismatched specifier type: %s", runTestNegative); + + it.each<[string, TypeOrValueSpecifier]>([ + ['type Test = Foo;', { from: 'lib', name: 'Foo' }], + ['type Test = Foo;', { from: 'lib', name: ['Foo', 'number'] }], + ])("doesn't match an error type: %s", runTestNegative); }); }); diff --git a/packages/typescript-estree/package.json b/packages/typescript-estree/package.json index b910c6d8b3b..1905ece14fc 100644 --- a/packages/typescript-estree/package.json +++ b/packages/typescript-estree/package.json @@ -58,7 +58,7 @@ "globby": "^11.1.0", "is-glob": "^4.0.3", "semver": "^7.5.0", - "ts-api-utils": "^1.0.0" + "ts-api-utils": "^1.0.1" }, "devDependencies": { "@babel/code-frame": "*", diff --git a/yarn.lock b/yarn.lock index 8e2d003073a..cbbf418e3f6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14979,10 +14979,10 @@ trough@^1.0.0: resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== -ts-api-utils@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.0.tgz#bec2b0f3af409e5acd547dbf1d14e8261459bc42" - integrity sha512-ycbj7cbgdeLc5i7xhxewYjWOoMzeVz4PiKvkWC/fVjfbt4ToHCvotIzD+GB1iYn1R+kaQG0JdET1ZNZwl4nXUQ== +ts-api-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.1.tgz#8144e811d44c749cd65b2da305a032510774452d" + integrity sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A== ts-essentials@^2.0.3: version "2.0.12"