• Similar to Decode.map, but you return a decoder instead of a value. This allows you to decide how to continue decoding depending on the result.

    Type Parameters

    • A

      Input to the mapping function

    • B

      The mapping function returns a decoder for this type

    Parameters

    • fn: ((a) => Decoder<B>)

      Mapping function that returns a decoder

    • child: Decoder<A>

      The decoder to run before the mapping function

    Returns Decoder<B>

    Example

    Maybe our HTTP API of choice wraps the data in an object that contains information about the success of the operation. Depending on that value we want to handle the data differently.

    const UserDecoder = Decode.object({
    id: Decode.field('id', Decode.integer),
    name: Decode.field('name', Decode.string),
    });

    const response_decoder = Decode.andThen(
    success => {
    if (success) {
    return Decode.field('data', UserDecoder);
    } else {
    return Decode.andThen(
    error => Decode.fail('Got an error response: ' + error),
    Decode.field('error', Decode.string),
    );
    }
    },
    Decode.field('success', Decode.bool),
    );

    // Works
    decode(response_decoder, {
    success: true,
    data: {
    id: 1,
    name: 'Kobe Bryant',
    },
    });

    // Fails
    decode(response_decoder, {
    success: false,
    error: 'Could not find user!',
    });

    This is nice and all, but it only works for the UserDecoder. However, making it generic is rather simple. You just wrap the Decoder in a function and accept the data decoder as an argument:

    function responseDecoder<T>(child: Decoder<T>): Decoder<T> {
    return Decode.andThen(success => {
    if (success) {
    return Decode.field('data', child);
    } else {
    // etc.
    }
    }, Decode.field('success', Decode.boolean');
    }

Generated using TypeDoc