a2ui-project / a2ui-project/a2ui

TypeScript code contains hundreds of references to `any` type, which disables type analysis

Abierto
#1,296 4 comentarios 0 reacciones 1 asignado Asignado a @josemontespg Ver en GitHub
P2 type: feature/enhancement
Lenguaje dominante
TypeScript
Estrellas
16.4k
Forks
1.3k
Merge medio
2 d 13 h
PR fusionados (30 d)
134

Descripción

If we enabled `@typescript-eslint/no-explicit-any: "error"` and ran `tsc --noImplicitAny`, **381 errors** would surface in production code that the currently are not flagged.

Each of these place where a type was either explicitly declared `any` (effectively turing off the type checker) or never specified at all (compiler couldn't infer). Each one is a hole through which a wrong type can flow into otherwise type-checked code.

Regardless of how many references of `any` turn out to actually be problematic, I suggest we turn on `no-explicit-any`, at least in non-test code. The whole purpose of the `any` super type, as far I am aware, is to allow gradual migration of JavaScript to TypeScript. This doesn't apply to this repo since the relevant code was written in TS to begin with. Even in places were the shape of an object cannot be known ahead of time, `unknown` can be used. TS's type system is very expressive--there's usually a way to keep things typed without great upfront cost even in scenarios where it is tempting to reach for `any` (e.g. discriminating union types, intersection types, mapped types, conditional types, template literal types, `infer`, etc.).

I suggest we turn on the rule sooner rather than later. The longer we put it off, the more expensive the issue becomes. I can personally say I've seen agents spending several inferences troubleshooting a bug that would have been immediately flagged with typechecking in my very brief time with this repo.

Use of `any` can also hide API design smells that. For example, being forced to write a very complicated or brittle type ([example](https://github.com/google/A2UI/blob/1e82275ec0644aea41471f53bbfd79587c9e6b44/renderers/angular/src/v0_9/core/types.ts#L70-L76)) often signals that an upstream type is loosely specified (e.g. a single blobby type with a bunch of optional fields was used where a discriminating union would more precisely capture that an object will match one of _N_ known shapes at runtime).

## Numbers

The following was gathered via an agent, but the full methodology is included afterwards to facilitate verification.

| Category | Errors |
|---|---:|
| **Published library code** *(`renderers/web_core`, `renderers/{angular,lit,react}`, `renderers/markdown/markdown-it`)* | **146** |
| **All other non-test code** *(samples, tools, spec eval)* | **235** |
| **Total** | **381** |

Test/spec code was excluded, though of course this could mask bugs as well.

Of the 381: **2 are implicit-any** (compiler couldn't infer) and **379 are explicit `any`** (written deliberately in source). Implicit-any is more or less fine here since we have `strict: true` in all our tsconfigs.

### Library breakdown

| Package | Errors |
|---|---:|
| `renderers/web_core` | 99 |
| `renderers/angular` | 29 |
| `renderers/lit` | 12 |
| `renderers/react` | 4 |
| `renderers/markdown/markdown-it` | 2 |

## Suggested fix

Enable `@typescript-eslint/no-explicit-any: "error"` in every workspace and gate CI on it. Fix or add `// eslint-disable-next-line` each existing site as a tracked decision rather than silent permission. Focus on library code first; samples/demos/tests can follow.

`web_core` has 99 explicit uses of `any`. [The eslint config defends this as necessary for generic library code](https://github.com/google/A2UI/blob/c55a37dc783146a607003ff3a3ecda92fbc36ac1/renderers/web_core/eslint.config.js#L33-L40). However--while I have not personally reviewed all uses--I have to imagine they are replaceable with `unknown` + narrowing or proper generic constraints. Adding [Type guards](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates) using `any` for the input parameter and removing `as any` casts that monkey-patch missing properties are probably the highest-leverage fixes we can do.

## Reproduction

Repo at `main` commit `c55a37dc`, all workspaces `npm install`ed first (otherwise `tsc` reports phantom errors from unresolved imports).

**Implicit any per workspace** (production code only):

```bash
cd
tsc --noEmit --noImplicitAny -p tsconfig.json 2>&1 \
| grep -vE '\.(test|spec)\.(ts|tsx)' \
| grep -cE 'error TS(7005|7006|7008|7009|7010|7011|7015|7017|7018|7019|7022|7023|7024|7031|7032|7033|7034)'
```

The TS70xx codes are TypeScript's "implicitly has an 'any' type" diagnostic family.

**Explicit any.** The following code performs a repo-wide AST walk that counts every `any` keyword in production `.ts`/`.tsx` files. Save as `count-any.js` and run from the repo root:

```js
// count-any.js
const ts = require('typescript');
const fs = require('fs');
const path = require('path');

const SKIP = new Set([
'node_modules', 'dist', 'build', 'out', 'coverage',
'.angular', '.next', '.wireit', '.git', 'worktrees',
]);
const TEST = /\.(test|spec)\.tsx?$|\/tests?\/|\/__tests__\//;

function* walk(dir) {
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
if (SKIP.has(e.name) || e.name.startsWith('.')) continue;
const p = path.join(dir, e.name);
if (e.isDirectory()) {
yield* walk(p);
} else if (
/\.tsx?$/.test(e.name) &&
!e.name.endsWith('.d.ts') &&
!TEST.test(p)
) {
yield p;
}
}
}

let total = 0;
for (const file of walk(process.cwd())) {
const sf = ts.createSourceFile(
file,
fs.readFileSync(file, 'utf8'),
ts.ScriptTarget.Latest,
/* setParentNodes */ false,
file.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS,
);
(function visit(node) {
if (node.kind === ts.SyntaxKind.AnyKeyword) total++;
ts.forEachChild(node, visit);
})(sf);
}
console.log(total);
```

```bash
node count-any.js
```

Equivalent to running ESLint with `@typescript-eslint/no-explicit-any: "error"` and counting violations, but this script works without needing per-workspace ESLint configuration.

Guía de contribución

Abrir la guía de contribución

Línea de trabajo

The issue identifies 381 `any` type references across multiple packages, with a script to count them. Start by enabling `@typescript-eslint/no-explicit-any: "error"` in the eslint configs for each workspace (e.g., renderers/web_core, angular, lit, react, markdown-it). Review the existing uses in library code first, replacing `any` with `unknown` or proper generic types. Run the provided reproduction commands to verify the count and ensure CI fails on new `any` usage. Focus on one package at a time, checking the TypeScript compilation and linting results.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
typescript
Área
backend-api-design, devtools
Tipo de issue
Refactorización
Dificultad
4/5
Tiempo estimado
3-5 días
Estado de actividad
Tranquilo
Claridad
Bien especificado
Aptitud para principiantes
45/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.