<story><title>From Rust to TypeScript</title><url>https://valand.dev/blog/post/from-rust-to-typescript</url></story><parent_chain><item><author>flowerlad</author><text>This article is unconvincing.&lt;p&gt;From the article: &lt;i&gt;Compared to the first snippet, this one is harder to debug. It seems so because 1.) You don&amp;#x27;t know that callMe will throw an error or not. 2.) If it throws an exception you will not know what is the type of the exception. The more modular your code is, the harder it is to debug exceptions.&lt;/i&gt;&lt;p&gt;This is only a problem with unchecked exceptions as seen in TypeScript and C#. Checked exceptions are the solution.&lt;p&gt;The problem with error code return is tediousness:&lt;p&gt;&lt;pre&gt;&lt;code&gt;  int foo() {
     int result = bar();
     if (result == ERROR_CODE)
        return result;
     int result2 = baz();
     if (result2 == ERROR_CODE)
        return result2;
     int result3 = bazz();
     if (result3 == ERROR_CODE)
        return result3;
  }
&lt;/code&gt;&lt;/pre&gt;
Compare to the same code written in a language that supports checked exceptions:&lt;p&gt;&lt;pre&gt;&lt;code&gt;  int foo() throws SomeException {
     int result = bar();
     int result2 = baz();
     int result3 = bazz();
  }
&lt;/code&gt;&lt;/pre&gt;
In the first version the logic is interspersed with error handling, which makes the logic hard to see.&lt;p&gt;How do people using Go and other languages that don&amp;#x27;t have exceptions solve this reduced readability problem?</text></item></parent_chain><comment><author>kibwen</author><text>The article doesn&amp;#x27;t get into it, but Rust has an error-handling operator, `?`, that encapsulates the branch-and-return-on-error check. Your code in Rust would look like:&lt;p&gt;&lt;pre&gt;&lt;code&gt;    fn foo() -&amp;gt; SomeResult {
        let result = bar()?;
        let result2 = baz()?;
        let result3 = bazz()?;
    }
&lt;/code&gt;&lt;/pre&gt;
The fundamental difference between Rust&amp;#x27;s approach and Java-style checked exceptions arises when those three functions have different error types. In Java, you would annotate the function with every possible exception that the function can throw. In Rust, a library (or module within a library) would normally design its own Result type to encompass every error that the library&amp;#x2F;module can throw, and use that type on every error-producing function (you &lt;i&gt;could&lt;/i&gt; reproduce the Java approach by defining a new Result type for each function, but I&amp;#x27;ve never seen anyone bother with that). The end result is that you avoid the precise bookkeeping that so annoys people about Java&amp;#x27;s checked exceptions, but you also tend to lose some precision with reading the code: from reading the type signature you know that a function with a custom error type has the potential to error, which is useful, and you know that the error must be &lt;i&gt;at least one&lt;/i&gt; of the types in the error&amp;#x27;s definition, but it might not exhibit &lt;i&gt;all&lt;/i&gt; of the error types that the custom error type can contain. Think of it like a spectrum: from not having any indication that that a function may error (e.g. JavaScript), to knowing that a function may error but not having any indication of how (Swift), to knowing a function may error with at least one of a known set of types (Rust), to knowing that a function may error with an exactly known set of types (Java with checked exceptions).</text></comment>
<story><title>From Rust to TypeScript</title><url>https://valand.dev/blog/post/from-rust-to-typescript</url></story><parent_chain><item><author>flowerlad</author><text>This article is unconvincing.&lt;p&gt;From the article: &lt;i&gt;Compared to the first snippet, this one is harder to debug. It seems so because 1.) You don&amp;#x27;t know that callMe will throw an error or not. 2.) If it throws an exception you will not know what is the type of the exception. The more modular your code is, the harder it is to debug exceptions.&lt;/i&gt;&lt;p&gt;This is only a problem with unchecked exceptions as seen in TypeScript and C#. Checked exceptions are the solution.&lt;p&gt;The problem with error code return is tediousness:&lt;p&gt;&lt;pre&gt;&lt;code&gt;  int foo() {
     int result = bar();
     if (result == ERROR_CODE)
        return result;
     int result2 = baz();
     if (result2 == ERROR_CODE)
        return result2;
     int result3 = bazz();
     if (result3 == ERROR_CODE)
        return result3;
  }
&lt;/code&gt;&lt;/pre&gt;
Compare to the same code written in a language that supports checked exceptions:&lt;p&gt;&lt;pre&gt;&lt;code&gt;  int foo() throws SomeException {
     int result = bar();
     int result2 = baz();
     int result3 = bazz();
  }
&lt;/code&gt;&lt;/pre&gt;
In the first version the logic is interspersed with error handling, which makes the logic hard to see.&lt;p&gt;How do people using Go and other languages that don&amp;#x27;t have exceptions solve this reduced readability problem?</text></item></parent_chain><comment><author>steveklabnik</author><text>In Rust, your code would look like this:&lt;p&gt;&lt;pre&gt;&lt;code&gt;  fn foo() -&amp;gt; Result&amp;lt;i32&amp;gt; {
      let result = bar()?;
      let result2 = baz()?;
      let result3 = bazz()?;
  }
&lt;/code&gt;&lt;/pre&gt;
(This wouldn&amp;#x27;t compile because you don&amp;#x27;t actually return anything in the success case, but I just kept the code the same. Additionally, I am assuming you are using some sort of crate that helps with error type mapping, because that&amp;#x27;s realistic, otherwise, it would be Result&amp;lt;i32, Error&amp;gt; where Error would be some sort of type mapping to SomeException&amp;#x27;s type.)</text></comment>