[config] Improve durableObject export error for invalid state properties#14648
Open
MattieTK wants to merge 1 commit into
Open
[config] Improve durableObject export error for invalid state properties#14648MattieTK wants to merge 1 commit into
MattieTK wants to merge 1 commit into
Conversation
The `exports.durableObject()` factory has five overloads, one per Durable Object `state`, each with a precise return type that downstream inference (e.g. `InferDurableNamespaces`) relies on. When a call matches no overload, TypeScript reports the *last* overload's error, so an invalid property such as `storage` on a `renamed` entry produced the misleading message `'"renamed"' is not assignable to type '"expecting-transfer"'`. Add a final fallback overload typed against the full discriminated union. When the precise overloads all fail, TypeScript falls back to it and, because the parameter is a discriminated union, performs a discriminant-aware excess-property check that points at the offending property directly: `'storage' does not exist in type 'DurableObjectRenamedExportOptions'`. Valid calls still resolve to a precise overload first, so return-type precision and existing inference behaviour are unchanged.
Contributor
|
Codeowners approval required for this PR:
Show detailed file reviewers |
Contributor
|
The change is a minimal, type-only addition. My analysis confirms:
The change is correct and low-risk. No actionable issues. LGTM |
@cloudflare/autoconfig
create-cloudflare
@cloudflare/deploy-helpers
@cloudflare/kv-asset-handler
miniflare
@cloudflare/pages-shared
@cloudflare/unenv-preset
@cloudflare/vite-plugin
@cloudflare/vitest-pool-workers
@cloudflare/workers-auth
@cloudflare/workers-editor-shared
@cloudflare/workers-utils
wrangler
commit: |
dario-piotrowicz
approved these changes
Jul 10, 2026
workers-devprod
approved these changes
Jul 10, 2026
workers-devprod
left a comment
Contributor
There was a problem hiding this comment.
Codeowners reviews satisfied
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Describe your change...
The
exports.durableObject()factory in@cloudflare/configuses five overloads, one per Durable Objectstate(created,deleted,renamed,transferred,expecting-transfer), each with a precise return type that downstream type inference (e.g.InferDurableNamespaces) relies on to distinguish live namespaces from tombstones. The problem is that when a user writes something TypeScript can't match to any overload – for example:exports: { NewCounter: exports.durableObject({ storage: "sqlite" }), Counter: exports.durableObject({ storage: "sqlite", state: "renamed", renamedTo: "NewCounter" }), }where
storageis invalid on arenamedentry – TypeScript falls back to reporting the last overload's error, which happens to beexpecting-transfer. So instead of telling you to removestorage, it says:This sends you down the wrong path:
expecting-transferis the state that accepts astorageobject, but the real problem is thatstorageshouldn't be present on arenamedentry at all.This PR adds one extra fallback overload at the end whose parameter is typed as the full discriminated union (
DurableObjectExportOptions) rather than a single state. When the five precise overloads all fail, TypeScript now falls back to this union overload, and because the parameter is a discriminated union it performs a discriminant-aware excess-property check: it readsstate: "renamed", narrows toDurableObjectRenamedExportOptions, and reports the offending property directly:The same improvement applies to the other states (e.g.
storageondeleted,renamedToontransferred).Crucially, valid calls still resolve to one of the five precise overloads first, so return-type precision – and therefore the existing inference behaviour that
InferDurableNamespacesdepends on – is completely unchanged. The union overload is only ever reached to produce a better error message.Known limitation: this only improves the error when the
statediscriminant is present, since union excess-checking can't flag a stray property when it can't tell which member you meant (e.g. omittingstateentirely and addingtransferFrom).tsctype-check. The@cloudflare/configpackage has no type-error-assertion harness, and the message wording isn't practically assertable in automated tests. Verified locally againsttscthat valid calls keep their precise return types and invalid calls now point at the offending property.