Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/provider.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,9 @@ If you have defined any `state`s in your consumer tests, the `Verifier` can put
const opts = {
...
stateHandlers: {
[null]: () => {
"null": () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm this actually just matches the string "null", and not a null handler. Perhaps we're better updating the types to support this more directly?

Copy link
Contributor Author

@zachlysobey zachlysobey Jun 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In JS, all object property keys (except for Symbols) are strings. When you use [null] like this, it coerces it to a string under the hood.

A few examples that demonstrate this

const obj = {};
obj[null] = 42;
console.log(obj); // { "null": 42 }
console.log(obj["null"]); // 42
Object.keys({ [null]: 1 }) // ['null']
Object.keys({ "null": 1 }) // ['null']
const obj1 = { [null]: 1, "null": 2 }
const obj2 = { "null": 2, [null]: 1 }
JSON.stringify(obj1) // '{"null":2}'
JSON.stringify(obj2) // '{"null":1}'

Copy link
Contributor Author

@zachlysobey zachlysobey Jun 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of those examples are how it works with the node REPL, or the browser console.
If you run those examples with ts-node (the TypeScript REPL) they all fail with runtime errors.
Compiling with tsc also fails for the same reason.

A computed property name must be of type 'string', 'number', 'symbol', or 'any'

This isn't a matter of updating the types or something. It's how TS was designed. They identify this pattern as confusing and problematic, and explicitly disallow it.

TS1170 has a bit more context

// This is the "default" state handler, when no state is given
}
},
"Has no animals": () => {
animalRepository.clear()
return Promise.resolve(`Animals removed from the db`)
Expand Down
Loading