The problem with new URL(), and how URL.parse() fixes that

JavaScript’s `new URL()` constructor currently throws on invalid input, prompting calls for a safer `URL.parse()` or `URL.canParse()` style API that returns a nullable or Result-like value instead. Commenters use this as a jumping-off point to compare error-handling strategies across languages—exceptions vs. `Result`/`Either`/`Option` types, checked vs. unchecked errors, and performance and ergonomics trade‑offs—arguing that “errors as values” often lead to clearer, more composable code. Others caution against proliferating overlapping APIs and suggest the real fix is better language-level support and syntax for handling failures consistently.

Error handling models: exceptions vs “errors as values”

  • Many argue URL parsing should use sum types like Result<T,E>/Either/Option, not exceptions.
  • Pro-“errors as values” points:
    • Function signatures clearly mark what can fail and how.
    • Callers are forced, by types, to consider failure.
    • Easier to distinguish fallible vs infallible code, encouraging more pure functions.
  • Pro-exception points:
    • Built-in stack traces and human-readable messages aid debugging.
    • Good for higher-level “bail out and log” behavior where local recovery is rare.
    • With sugar (try, ?), ergonomics can be similar to Result types.
  • Some note Swift’s throws is essentially sugar over Result, and its try? / try! variants let you choose optional/abort semantics.

Checked exceptions, Result types, and language comparisons

  • Java’s checked exceptions are cited as awkward: verbose throws lists, weak composition with higher-order functions, and poor stdlib modeling (e.g., very broad IOException).
  • Others counter that the concept is sound; the problems are ergonomic and historical, not fundamental.
  • Rust’s Result + ? is praised for ergonomics but criticized for missing stack traces and encouraging error propagation without added context.
  • Go’s manual if err != nil chaining is seen as verbose and error-prone.

JavaScript’s new URL(), URL.parse, and canParse

  • new URL() throwing is viewed as inconvenient when you just want “parse or fail fast” behavior in an expression or const assignment.
  • Many prefer a non-throwing URL.parse / URL.canParse style; others say a simple helper around try/catch is enough and standardizing more variants bloats the API surface.
  • There’s concern that adding multiple overlapping entry points (new URL, URL.parse, URL.canParse) fragments the API and increases engine/JIT attack surface.

JS ergonomics: try/catch, const, and syntax sugar

  • Multiple comments complain that try/catch interacts poorly with const (you must declare then assign), leading to awkward patterns (IIFEs, proposed “write-once const”, do expressions).
  • Some wish for language-level sugar to convert exceptions into nullable/Result-style values directly, instead of teaching every class to return null.

URL parsing semantics and edge cases

  • Discussion notes:
    • new URL("/path") requires a base URL; HTML attributes like src accept relative references, which are subtly different.
    • new URL accepts bare scheme: strings as valid custom protocols, which is correct per URI rules but surprising when using it as a heuristic “does this look like a web URL?”.
    • Differentiation between URL vs URI vs URI-reference is raised but acknowledged as largely academic in everyday JS use.