Skip to content

Commit

Permalink
fix(type-utils): treat intrinsic types as if they are from lib and ne…
Browse files Browse the repository at this point in the history
…ver match error types (#6869)

* 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 ✨ <git@joshuakgoldberg.com>
  • Loading branch information
RebeccaStevens and JoshuaKGoldberg committed Jul 7, 2023
1 parent 02a37c4 commit ecb57de
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 10 deletions.
2 changes: 1 addition & 1 deletion packages/eslint-plugin/package.json
Expand Up @@ -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": "*",
Expand Down
2 changes: 1 addition & 1 deletion packages/type-utils/package.json
Expand Up @@ -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",
Expand Down
26 changes: 23 additions & 3 deletions 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 {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand Down
18 changes: 18 additions & 0 deletions packages/type-utils/tests/TypeOrValueSpecifier.test.ts
Expand Up @@ -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;',
Expand Down Expand Up @@ -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);
});
});
2 changes: 1 addition & 1 deletion packages/typescript-estree/package.json
Expand Up @@ -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": "*",
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Expand Up @@ -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"
Expand Down

0 comments on commit ecb57de

Please sign in to comment.