diff --git a/apps/oxlint/package.json b/apps/oxlint/package.json index 9e2e9a1946baa..c7a7fad2cde4e 100644 --- a/apps/oxlint/package.json +++ b/apps/oxlint/package.json @@ -39,6 +39,7 @@ "@arethetypeswrong/core": "catalog:", "@babel/code-frame": "^7.28.6", "@napi-rs/cli": "catalog:", + "@type-challenges/utils": "^0.1.1", "@types/babel__code-frame": "^7.27.0", "@types/esquery": "^1.5.4", "@types/estree": "^1.0.8", diff --git a/apps/oxlint/src-js/visitor.test-d.ts b/apps/oxlint/src-js/visitor.test-d.ts new file mode 100644 index 0000000000000..d4365e751d570 --- /dev/null +++ b/apps/oxlint/src-js/visitor.test-d.ts @@ -0,0 +1,68 @@ +import type { ExpectExtends, ExpectTrue, ExpectFalse } from "@type-challenges/utils"; +import type { VisitorObject } from "./generated/visitor.d.ts"; +import type { Node, CallExpression } from "./generated/types.d.ts"; + +// Empty visitor object is allowed +const emptyVisitor = {}; +export type _Empty = ExpectTrue>; + +// Specific node visitors have a stricter type for the parameter +const callExpressionVisitor = { + CallExpression: (_node: CallExpression) => {}, +}; +export type _CallExpr = ExpectTrue>; + +const callExpressionExitVisitor = { + "CallExpression:exit": (_node: CallExpression) => {}, +}; +export type _CallExprExit = ExpectTrue< + ExpectExtends +>; + +const debuggerStatementWrongTypeVisitor = { + DebuggerStatement: (_node: CallExpression) => {}, +}; +export type _DebuggerStmtWrongType = ExpectFalse< + ExpectExtends +>; + +// Node selectors have generic `Node` type for the parameter +const selectorsVisitor = { + "FunctionExpression > Identifier": (_node: Node) => {}, + ":matches(FunctionExpression, FunctionDeclaration)": (_node: Node) => {}, +}; +export type _Selectors = ExpectTrue>; + +// Visitor functions can omit the node parameter +const callExpressionNoParamVisitor = { + CallExpression: () => {}, +}; +export type _CallExprNoParam = ExpectTrue< + ExpectExtends +>; + +// Properties of visitor object can be `undefined`. +// Ideally we'd disallow this, but it's not possible without `exactOptionalPropertyTypes: true` in `tsconfig.json`. +// Obviously we can't force that on users. +const callExpressionUndefinedVisitor = { + CallExpression: undefined, +}; +export type _CallExprUndefined = ExpectTrue< + ExpectExtends +>; + +// Other types are not allowed +const invalidNullVisitor = { + CallExpression: null, +}; +export type _InvalidNull = ExpectFalse>; + +const invalidObjectVisitor = { + CallExpression: {}, +}; +export type _InvalidObject = ExpectFalse>; + +const invalidStringVisitor = { + CallExpression: "oh dear", +}; +export type _InvalidString = ExpectFalse>; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a19ce85b99469..5fe7e37c102f0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -111,6 +111,9 @@ importers: '@napi-rs/cli': specifier: 'catalog:' version: 3.5.1(@emnapi/runtime@1.8.1)(@types/node@24.1.0) + '@type-challenges/utils': + specifier: ^0.1.1 + version: 0.1.1 '@types/babel__code-frame': specifier: ^7.27.0 version: 7.27.0 @@ -2595,6 +2598,9 @@ packages: '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@type-challenges/utils@0.1.1': + resolution: {integrity: sha512-A7ljYfBM+FLw+NDyuYvGBJiCEV9c0lPWEAdzfOAkb3JFqfLl0Iv/WhWMMARHiRKlmmiD1g8gz/507yVvHdQUYA==} + '@types/babel__code-frame@7.27.0': resolution: {integrity: sha512-Dwlo+LrxDx/0SpfmJ/BKveHf7QXWvLBLc+x03l5sbzykj3oB9nHygCpSECF1a+s+QIxbghe+KHqC90vGtxLRAA==} @@ -6573,6 +6579,8 @@ snapshots: dependencies: tslib: 2.8.1 + '@type-challenges/utils@0.1.1': {} + '@types/babel__code-frame@7.27.0': {} '@types/chai@5.2.3':