Skip to content

Coercing a refined struct doesn't trigger refinement #1278

@yeoffrey

Description

@yeoffrey

Consider this example, where we have a refiner and a coercer:

import { coerce, create, number, refine, string } from 'superstruct'

const BigNumber = refine(number(), 'Big Number', (value) => {
    return value > 100 ? true : "Number isn't big enough!"
})

const StringBigNumber = coerce(string(), BigNumber, (value) => {
    return `${value}`
})

Based on the documentation on coercing data:

The second argument to coerce is a struct narrowing the types of input values you want to try coercion. In the example above, the coercion function will only ever be called when the input is a string—booleans would ignore coercion and fail normally.

Expected

This implies to me that the coercer will only run if the number is a valid BigNumber. If it fails, then I should expect the error message to contain the message from the refiner.

// ... above code
create(30, StringBigNumber) // Fails, "Number isn't big enough!"
create('hello', StringBigNumber) // Fails, "Expected a number, but received: "hello""

Actual

The coercer skips the refiner entirely, ignoring its validation and just checking that it

// ... above code
create(30, StringBigNumber) // Fails, "Expected a string, but received: 30"
create('Hello!', StringBigNumber) // Pass, not even a number

Is this intentional? To me the documentation says it should first pass the second struct, and then do coercion, then pass the first struct.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions