Live data from Hacker News

TypeScript 3.7

typescriptlang.org

131–140 of 167 posts

Re: TypeScript 3.7

#132

Earlier quoted context omitted.

Sorry, JS? While JS might get this stuff one day, these language features are for TypeScript which is its own language. It's strongly typed and just happens to interop with and in some scenarios transpile down to JavaScript. It's whole existence is to deal with that billion dollar mistake you mentioned. Speaking of which, optional chaining and null coalescence are core language features of some very good languages. K…

> optional chaining and null coalescence are core language features of some very good languages They are features of Maybe/Option too, just in a more consistent extensible way. val a = Some(thing) val b = a.flatMap(_.part).flatMap(_.subpart) val c = Some(None) // look Ma! a nested option! > While JS might get this stuff one day I appreciate the attempt at pedantry, but TypeScript general only implements JS language f…

Show me where decorators are in the ecmascript standard.

How about private variables in classes? (Hint: they're different)

Typescript is a superset not just typed JavaScript.

Re: TypeScript 3.7

#133

I'm a big fan of the new operators. One of my remaining gripes with Javascript/Typescript is the try/catch mess around await. It makes assignment of const a pain for async calls that may reject. e.g. let result: SomeType; try { result = await funcThatReturnSomeType(); } catch (err) { doSomethingWithErr(err); } // at this point result is `SomeType | undefined` if (result) { doSomething(result); } I really want some ki…

Can you hoist the `if (result)` into the `try` part of the statement? (Without seeing more context hard to know why that wouldn't work for you). Another pattern to avoid the above is to remember that async functions return promises and that .catch() also returns a promise. So your above logic can be written as: const result = await funcThatReturnSomeType().catch(doSomethingWithErr); if (result) { doSomething(result);…

> Can you hoist the `if (result)` into the `try` part of the statement?

And now you wrap the function call to doSomething() in the try/catch too. Often (usually?) the try/catch specifically is for the asynchronous function. Usually that's because the async. stuff might fail due to expectable (even if undesirable) runtime conditions (e.g. "file not found"), while synchronous code should work for the most part (external condition errors vs. coding errors - and your catch is about the former, because, for example, you might want coding errors to just crash the app and be caught during testing).

Sure, you can claim that you check for specific errors that could only happen in that function, so that any errors occurring in doSomething() don't matter/don't change the outcome, or that doSomething never throws because you are sure of the code (the async. function may throw based on runtime conditions, but you may have development-time control over any issues in doSomethign() - but if you start going down that path, having to rely on the developer doing there job perfectly for each such construct, later maintainability and readability goes down the drain. You would have to make sure such a claim is valid when you later come across the construct. That is why you really don't want anything inside the try/catch from which you don't want to see any errors in the catch block. So my policy is to never ever do that even if in the given context it would work - it places additional work on whoever is going to read that section later (or they are ignorant of the problem and won't see this potential problem, which is not any better).

Re: TypeScript 3.7

#134

I'm a big fan of the new operators. One of my remaining gripes with Javascript/Typescript is the try/catch mess around await. It makes assignment of const a pain for async calls that may reject. e.g. let result: SomeType; try { result = await funcThatReturnSomeType(); } catch (err) { doSomethingWithErr(err); } // at this point result is `SomeType | undefined` if (result) { doSomething(result); } I really want some ki…

Could do something like this:

    async function test() {
        const promise = Math.random() 

Re: TypeScript 3.7

#135
post #126
post #124

Earlier quoted context omitted.

> It does not interop with JavaScript. I don't know what you mean here, but it is certainly possible for TypeScript code to use JavaScript libraries and vice versa, which is presumably what most people mean by "TypeScript interops with JavaScript". > It always transpiles to JavaScript and always runs as JavaScript. Technically false... https://assemblyscript.org > TypeScript is a superset of JavaScript. Therefore the…

> I don't know what you mean here, but it is certainly possible for TypeScript code to use JavaScript libraries and vice versa, which is presumably what most people mean by "TypeScript interops with JavaScript". Ah, I can see what you/they mean by that. The point I was trying to get across was: TypeScript doesn't exist when code is actually executing (which is what I think of as interop - it's happening at execution…

> The Million Dollar Mistake is having unchecked nulls; TypeScript supports checked nulls so it's not an issue. TypeScript's nulls are much more similar to Maybe/Option than unchecked nulls

Good point in theory but my practical experience hasn't borne this out. That is because TypeScript is an "optionally typed" language and it hasn't been true in practice because of excessive use of explicit or implicit "any"s.

I think that's a matter of your team's discipline. It's good practice, I think, to enable TypeScript's strict checks, including no-implicit-any, and, to the best of your ability, to keep people who don't understand types ignorant of explicit any and to fail any code that uses it. `any` is basically never necessary even in typing existing code - if you genuinely don't know what the type is at a certain point, you should probably write a type like `unknown`.

If you take any of Typescript's options to "ease the transition" you're taking Typescript's options to continue the difficulties. One moves to typescript because javascript's runtime errors are a problem; so it is natural that you will have novel compile time errors.

Re: TypeScript 3.7

#137
post #79

Earlier quoted context omitted.

You can also get rid of `if(result){}` by setting the return type of "doSomethingWithErr" to "never": function doSomethingWithErr(err: any): never { throw new Error("Oops"); } let result: SomeType; try { result = await funcThatReturnSomeType(); } catch (err) { doSomethingWithErr(err); } // because doSomethingWithErr has return type "never", result will be definitely assigned. doSomething(result); ..or just return in…

Interestingly when I was encountering this myself recently, I discovered that JS finally blocks can return after a function has nominally already returned. Consider the following closure. (() => { try { // finally will return prior to this console.log console.log('this try was executed and the return ignored') return 'try block' } catch (e) { return 'error block' } finally { return 'finally block' } })()

I don't think that's the right way of thinking about it. The behavior I see is consistent with my understanding of `finally` from other languages.

Basically, `finally` gives you a guarantee that it will actually run once the `try` block is exited. Likewise, `return` effectively assigns the return value and exits. But it doesn't (cannot and should not) breach the contract of try-finally, since the purpose of try-finally is to ensure resources are managed correctly, so it either exits to the caller or it exits to the finally block, depending on which one is most recent.

In your case, a return value is assigned and the `try` block is exited using `return`. We then have to continue into the `finally` block, since that is the core meaning of `finally` - we run it after we leave `try`. And then with `return`, we reassign the return value and finally leave the whole function. At this point, the return value is the second one that was assigned to it.

Maybe thinking of it like this is helpful, although I somewhat hope it isn't. You can see that "return" is reassigned before we have a chance to read it. I've simplified by removing any consideration of errors, but I console.logged the final output.

    //this is the function call at the end of your IIFP
    next_code.push(AfterMe)
    goto Anonymous

    // this is the function definition
    Anonymous:
        // this is the try-finally idiom
        next_code.push(FinallyBlock);
        //this is the try
        console.log("this try was executed");
        //these two lines are the first return
        var return = 'try block';
        goto next_code.pop();
        //this is the finally
        FinallyBlock:
            var return = 'finally block'
            goto next_code.pop();

    // this code gets executed from the FinallyBlock's goto and is as if you have a console.log(..) around your whole definition.
    AfterMe:
        console.log(result)

Re: TypeScript 3.7

#138
post #67

I just did some refactoring on a medium size code base and here are a few things to watch out for when adopting optional chaining and the new null coalescing operator: foo && await foo(); is not the same as await foo?.(); this will work in most cases but subtly, the await wraps the undefined case into a Promise, while the original code would skip the await altogether. String regular expression matching returns null,…

&& ?. || ?? It's a shame JS at the beginning doubled down on the "billon dollar mistake" [1] with two(!) kinds of NULL instead of just using Maybe/Option. Ah well, if it were good it wouldn't be popular :/ [1] https://www.lucidchart.com/techblog/2015/08/31/the-worst-mis...

Going between rust and ts, it's the judicious use of enums that js really feels like it's missing. The whole hoopla with undefined/null/NaN/etc could be avoided with a simple enum type. Not to mention the entire concept of Exceptions.

Nullish alone had me back to the == instead of === once I went ts. No reason to care about identity when ts makes sure I don't compare a string to a number, but treating undefined == null as true is what I want 99.9% of the time, and that 0.1% I should be explicit that I do care about treating them differently.

Re: TypeScript 3.7

#139

I'm a big fan of the new operators. One of my remaining gripes with Javascript/Typescript is the try/catch mess around await. It makes assignment of const a pain for async calls that may reject. e.g. let result: SomeType; try { result = await funcThatReturnSomeType(); } catch (err) { doSomethingWithErr(err); } // at this point result is `SomeType | undefined` if (result) { doSomething(result); } I really want some ki…

IIFEs are an option: const result = await (() => { try { return funcThatReturnSomeType(); } catch (err) { doSomethingWithErr(err); } })();

Iffys are a nice go-to in ts in general, because type inference is so handy and I'd rather not have a big pile of typed `let`s at the top that I have to assign into later. Even something as simple as a switch plays nicer if you iffy it and use it like an expression (similar to a match is rust)

Re: TypeScript 3.7

#140

Earlier quoted context omitted.

&& ?. || ?? It's a shame JS at the beginning doubled down on the "billon dollar mistake" [1] with two(!) kinds of NULL instead of just using Maybe/Option. Ah well, if it were good it wouldn't be popular :/ [1] https://www.lucidchart.com/techblog/2015/08/31/the-worst-mis...

Sorry, JS? While JS might get this stuff one day, these language features are for TypeScript which is its own language. It's strongly typed and just happens to interop with and in some scenarios transpile down to JavaScript. It's whole existence is to deal with that billion dollar mistake you mentioned. Speaking of which, optional chaining and null coalescence are core language features of some very good languages. K…

> TypeScript which is its own language. It's strongly typed and just happens to interop with and in some scenarios transpile down to JavaScript. It's whole existence is to deal with that billion dollar mistake you mentioned.

I'm afraid literally everything in this snippet is incorrect. The Typescript website opens with:

> Typescript JavaScript that scales. Typescript is a typed superset of JavaScript that compiles to plain JavaScript.

Typescript is Javascript. It's a superset, and as such its improvements are additive-only, by definition. The purpose of its existence is not to change or replace any JS features, only to augment them.

Post reply on HN