Skip to content

Give createResource the source type it needs - #997

Merged
epompeii merged 2 commits into
develfrom
claude/console-check-solid
Aug 22, 2026
Merged

Give createResource the source type it needs#997
epompeii merged 2 commits into
develfrom
claude/console-check-solid

Conversation

@epompeii

Copy link
Copy Markdown
Member

astro check reports 806 errors. This takes it to 754, below the 758 it sat at
before the Astro 7 upgrade.

What was actually wrong

createResource is called in two shapes. The (source, fetcher) shape was
being given a single explicit type argument:

const [usage, { refetch }] = createResource<null | JsonUsage>(fetcher, fetchPlan);

That call has always been wrong. It reproduces under the pre-upgrade toolchain,
so the upgrade did not break these call sites; it changed what happens after
they fail. solid-js 1.9.14 added I = T to the (fetcher, options) overload,
whose return type became InitializedResourceReturn<T | I, R>. When resolution
falls through to it, T is left unresolved and leaks into the resource type, so
a single bad call now also produces errors at every consumer of that resource.
That cascade is what this removes.

The fix names the source type as well, which lets the intended overload match:

const [usage, { refetch }] = createResource<
  null | JsonUsage,
  ReturnType<typeof fetcher>
>(fetcher, fetchPlan);

ReturnType<typeof fetcher> rather than the object type spelled out, because it
stays in step with the source memo and supplies a contextual type at sites whose
fetcher is an inline arrow with nothing to copy from.

Why not just drop the type argument

Removing the explicit type argument also silences the errors, and it is the
wrong fix. These fetchers end in httpGet(...).then((resp) => resp?.data), and
.data is any, so inference resolves the whole resource to any. Both
approaches reach zero errors, so error counts cannot tell them apart. Two
independent probes confirmed the difference: under inference the resource
assigns to a deliberately incompatible type with no complaint, which only any
does, while naming the source type yields JsonUsage | null | undefined.

Trading a loud error for a silent any would have made this worse, not better.

Four resources that were declared as something they never return

getAuthUser, acceptInvite, and claimProject navigate; they return
void | null, never JsonAuthUser, JsonAuthAck, or JsonOrganization. All
three resources are discarded at the binding. getKey has a bare return, so
it is void, not undefined. Naming the source type is not enough at these
four, because the declared T was the lie. Each carries a suppression naming
the function, matching the convention already used in 24 other files.

Verification

  • astro check 806 to 754. 58 errors removed, 6 added.
  • The 6 added are not regressions: 3 are the same diagnostics at the same
    positions, relabelled because the resource finally resolves, and the other 3
    are latent problems that correct resolution stops masking.
  • No new any. All 26 edited sites resolve to concrete types, and the
    implicit-any count drops from 219 to 214.
  • Types only. Every one of the 13 changed files compiles to byte-identical
    JavaScript, so the reindentation carries no behavior.
  • biome ci exits 0 at the same 39 warnings as before, vitest passes, and the
    Cloudflare build path succeeds.

Left alone

15 call sites still fail. Each needs a real typing decision rather than a type
argument: 11 where the source memo is genuinely looser than the fetcher's
parameter annotation, and 4 where the declared type is wrong but the resource is
consumed, so an honest type would push errors into consumers. Those are runtime
changes and do not belong in a types-only change.

`createResource(source, fetcher)` takes two non-defaulted type parameters,
`T` and `S`. TypeScript has no partial type argument inference, so a call
that supplies only `T` cannot select that overload at all: it falls
through to the `(fetcher, options)` overload, which needs only `T`, and
the call is reinterpreted with the source accessor standing in for the
fetcher.

Passing `S` as well selects the intended overload. `S` is written as
`ReturnType<typeof <source>>` rather than a copy of the fetch function's
parameter annotation: it is exact, it stays in step with the source memo,
and it supplies the contextual type at the sites whose fetcher is an
inline arrow with no annotation to copy.

Dropping the explicit `T` instead and letting inference run would also
silence the errors, but most of these fetchers return
`httpGet(...).then((resp) => resp?.data)` and axios types `.data` as
`any`, so `T` would infer as `any` and the resource would lose its type
rather than regain it. Verified by assigning each resource to an
incompatible type and reading what the compiler reports: with `T`
inferred it reports nothing, because `any` is assignable to anything.

22 call sites. The resources now resolve to the types they always
claimed, for example `JsonUsage | null | undefined` in `BillingPanel`
and `JsonPlot | undefined` in `Pinned`.
Four call sites named a result type their fetch function never returns,
so pinning the source type argument was not enough to select the
`(source, fetcher)` overload.

`getAuthUser`, `acceptInvite`, and `claimProject` navigate and report
through `navigateNotify`; every path returns `null` or nothing, never a
`JsonAuthUser`, `JsonAuthAck`, or `JsonOrganization`. All three resources
are already discarded at the binding, so the declared type was decorative.
They are now `void | null`, and the two type imports that only the old
declarations used are dropped.

`getKey` returns a bare `return;` on its guard paths, which is `void`
rather than `undefined`, so the declared `undefined | JsonProjectKey |
JsonProjectKeyCreated` never matched. Widened to `void`.

`void` in a union reads as a mistake often enough that Biome flags it, so
each one carries a suppression saying which function produces it.
@epompeii epompeii added the javascript Pull requests that update Javascript code label Aug 22, 2026
@epompeii
epompeii marked this pull request as ready for review August 22, 2026 20:19
@epompeii
epompeii merged commit 893610e into devel Aug 22, 2026
39 checks passed
@epompeii
epompeii deleted the claude/console-check-solid branch August 22, 2026 20:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

javascript Pull requests that update Javascript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant