Disable single posts, but keep archive

One approach could be forcefully setting 404 status for single post. Please check following example. In case of singular post, query status is set to 404.

function theme_slug_customize_single_post() {
  if ( is_singular( 'post' ) ) {
    global $wp_query;
    $wp_query->set_404();
    status_header(404);
  }
}
add_action( 'wp', 'theme_slug_customize_single_post' );