From 2a846bee52c4561238f6823c474385eb166ff88b Mon Sep 17 00:00:00 2001 From: Max B Date: Sun, 23 Aug 2026 21:33:37 +0200 Subject: [PATCH] fix: erase non-validatable `as T` casts instead of SC1090 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the inner expression is `jsval` (an island handle) and the cast target is either: - itself `jsval`-mapped (an npm/ambient type with no static shape, e.g. Drizzle ORM builder types), or - not boundary-safe (a function type, callable record, class instance — anything that can't be JSON-validated), the compiler previously produced `SC1090: a checked cast of 'any' to 'any' is not supported yet` (for jsval targets) or a similar unsupported diagnostic (for non-boundary-safe targets). Both cases are TypeScript-only assertions with no runtime representation. The value is already an opaque island handle; the `as T` annotation is structural information for the type checker, not a runtime narrowing that can be validated. The correct behavior is erasure — return the inner value unchanged. `jsExit` is still emitted for JSON-representable (boundary-safe) targets where actual runtime validation is both possible and meaningful. --- .../compiler/src/frontend/lowering/lower-exprs.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/compiler/src/frontend/lowering/lower-exprs.ts b/packages/compiler/src/frontend/lowering/lower-exprs.ts index b0f1f0973..07ab7b76d 100644 --- a/packages/compiler/src/frontend/lowering/lower-exprs.ts +++ b/packages/compiler/src/frontend/lowering/lower-exprs.ts @@ -7147,15 +7147,12 @@ export function lowerTemplate(L: Lowerer, expr: ts.TemplateExpression): IrExpr { if (targetTs.flags & ts.TypeFlags.Any) return inner; const target = L.mapTypeOf(targetTs); if (!target) L.badType(expr.type, targetTs); - if (!L.boundarySafe(target)) { - L.unsupported( - "SC1090", - expr, - `a checked cast of 'any' to '${L.fmt(target)}' ` + - `(an 'any' value can only be validated against JSON-representable types: ` + - `number, string, boolean, records, arrays, and unions of those)`, - ); - } + // A target type that ITSELF maps to jsval — same erasure as the Any fast-path above. + if (target.kind === "jsval") return inner; + // Non-boundary-safe targets (functions, callable records, class instances, etc.) + // cannot be JSON-validated. JSVAL is already an opaque engine handle — the `as T` + // assertion is TypeScript-only and should erase rather than attempt validation. + if (!L.boundarySafe(target)) return inner; return { kind: "jsExit", value: inner, type: target, loc: locOf(expr) }; } const targetTs = L.checker.getTypeFromTypeNode(expr.type);