widget_posts_args not using the number of posts in widget

The problem is that you’re not modifying the existing arguments for the widget, you’re replacing them:

add_filter('widget_posts_args', function() {
    $params['post_type'] = array('post', 'recipe');
    return $params;
});

The result of that filter will be:

$params = [
    'post_type' => [ 'post', 'recipe' ]
];

So any other arguments, including the default number of posts, are removed.

This is because you’re not accepting the original value into your filter. Your callback function needs to accept this as an argument, so that you can modify and return it:

add_filter('widget_posts_args', function( $params ) {
    $params['post_type'] = array('post', 'recipe');
    return $params;
});

This is how filters work. You use a function that accepts the original value, and returns a new value.