
TypeScript 3.7 Beta - sebazzz
https://devblogs.microsoft.com/typescript/announcing-typescript-3-7-beta/
======
Epskampie
Looks nice. I love how dedicated typescript is to sticking to standard
javascript, even by championing features through the ecmascript standards
track.

They understand very well how bad it would be if the two languages were to
diverge.

~~~
munchor
Yes, I agree. I also think that if they were starting out today, they wouldn't
have either Enums or Namespaces since those features require adding runtime
code (as opposed to every other TS feature which is erasable). However, when
they started out, JavaScript wasn't as evolved (and it didn't look like it
would evolve this much) and so they had to add a few things "on their own".

~~~
azangru
I started writing this comment thinking "no way, enums make so much sense",
but then remembered Flow, where an enum is modelled simply as a union type,
and agree that that approach would have probably been better.

~~~
skrebbel
Yep, and nowadays TS has string literal types and unions so enums are pretty
much obsolete.

    
    
        type Direction = "up" | "down";

~~~
redact207
Enums and string literals aren't completely interchangable.

Enums are transpired to objects so you can iterate the keys/values. You can't
do that with SL which are a transpiler feature only.

Also you can't codedoc string literal values like you can with enums where it
shows up with intellisense.

I tend to prefer enums as a result

~~~
reaktivo
Since TS 3.4 you can have enum-like behaviour by using the `as const`
annotation on object and array literals.

    
    
        const types = ['x', 'y', 'z'] as const;
        const a: typeof types[number] = 'a'; // not ok
        const b: typeof types[number] = 'z'; // ok

~~~
styfle
Not to be confused with `const enum` which act more like a preprocessor and
emits in the value at compile time.

    
    
        const enum Directions { Up, Down, Left, Right }
        console.log(Directions.Left)
        // emits js file with console.log(2)
    
    

[https://www.typescriptlang.org/docs/handbook/enums.html#cons...](https://www.typescriptlang.org/docs/handbook/enums.html#const-
enums)

------
thisBrian
Slightly OT, but for those not aware: typescript's type system is turing-
complete[0], and there's a playground demonstrating number base conversion[1].

0:
[https://github.com/Microsoft/TypeScript/issues/14833](https://github.com/Microsoft/TypeScript/issues/14833)

1:
[https://github.com/Microsoft/TypeScript/issues/14833#issueco...](https://github.com/Microsoft/TypeScript/issues/14833#issuecomment-535858897)

------
munchor
"Assertion Functions" are quite interesting. When we moved from Flow to
TypeScript, this was the number 1 thing that frustrated us about TypeScript.
The issue is that we had a lot of calls like this:

``` function assert(condition: boolean, message: string) { if (!condition) {
throw new Error(message); } }

assert(x !== null, "x can't be null");

// Flow understands that x can't be null here because `invariant` throws an
error otherwise, but TS doesn't ```

However, TypeScript couldn't understand that `x` can't be null after that call
since it doesn't understand what `assert` does. For that reason, we had to
write a codemod that replaced all of our `assert` calls with an if condition
that threw an error inline.

The new `asserts` syntax is nice (it would be even better if TS could do this
automatically like Flow though), and will be a much welcome update for us.

~~~
deepersprout
I don't get Assert Functions.

What are they good for? Maybe there is a use case I am not getting, but this

    
    
      function yell(str) {
        assert(typeof str === "string");
    
        return str.toUppercase();
        //         ~~~~~~~~~~~
        // error: Property 'toUppercase' does not exist on type 'string'.
        //        Did you mean 'toUpperCase'?
      }
    
      function assert(condition: any, msg?: string): asserts condition {
        if (!condition) {
            throw new AssertionError(msg)
        }
      }
    

Seems like the equivalent to

    
    
      function yell(str : String) {
        return str.toUppercase();
        //         ~~~~~~~~~~~
        // error: Property 'toUppercase' does not exist on type 'string'.
        //        Did you mean 'toUpperCase'?
      }
    
    

But the latter has much less code and is clearer too.

What am I missing?

~~~
bsaul
I’m not sure that’s what you’re asking, but assertion are often used to
trigger error in debug mode on runtime properties not covered by the type
system (array having a min / max number of elements, code being executed in a
background thread, etc..).

~~~
deepersprout
I still don't get it. Please help me out.

Why should the type system have anything to do with something like this?

    
    
      function something(num : number) {
        assertIsInRange(num);
      
        return num + 1;
      }
      
      function assertIsInRange(num: number, msg?: string): asserts num {
        if (num < 50 || num > 100) {
          throw new Error('not in range');
        }
      }
      
      something(50);
    
    

How is `asserts num` helping here?

~~~
mceachen
If your something function was `something (num: string|number)`, typescript
can safely trust that`num` is a number in the block proceeded by your call to
assert because it knows it must be a number, not a string.

~~~
deepersprout
If the `something` function had `(num: string | number)` I would not be able
to call `assertIsInRange(num: number)` because `Argument of type 'string |
number' is not assignable to parameter of type 'number'.`

So If I wanted to do that I would have to

    
    
      if (typeof num === 'number') {
        assertIsInRange(num);
      }
    

anyway.

I think I still don't get it.

------
blobs
> The star of the show in optional chaining is the new ?. operator for
> optional property accesses.

Wow, that took a while! For already about 9 years this feature is in
Coffeescript. And indeed it must be the star of the show because once you're
used to that you almost can't live without it. Why did JS/ESxx never copied
that idea?

edit: just read it has just been added to JS some days ago as well..

~~~
rimunroe
This may feel a bit nit-picky, but they haven't been added to ECMAScript yet.
There are two features here: the optional chaining operator[1] and nullish
coalescing operator[2]. Both are at stage 3 of the standardization process.

Changes to proposed features can still be made at stage 3 if critical issues
come up. Otherwise, once implementors have sufficient experience with them
(and tests & multiple implementations exist) the proposals will be eligible to
move to stage 4, after which they'll be able to be included as part of the
next ECMAScript spec.

Both proposals are progressing through the process very smoothly, but I
wouldn't rely on them for anything critical just yet.

[1] [https://github.com/tc39/proposal-optional-
chaining](https://github.com/tc39/proposal-optional-chaining)

[2] [https://github.com/tc39/proposal-nullish-
coalescing](https://github.com/tc39/proposal-nullish-coalescing)

~~~
styfle
Thats a good point. It is probably rare for proposals to change after stage 3
which is why the TypeScript team does not implement a ECMAScript feature until
it reaches Stage 3.

In this case, members of the TS team were actually championing these ES
proposals :)

------
dtech
Really nice, I work in a project with a lot of nested optional values, and all
the `a && a.b && a.b.c && a.b.c.d` checks really introduce a lot of noise.

~~~
manojlds
Mostly it's a code smell though

[https://en.m.wikipedia.org/wiki/Law_of_Demeter](https://en.m.wikipedia.org/wiki/Law_of_Demeter)

~~~
zhirzh
I'd say it is a design smell and not necessarily code smell. Any API or data
interface should try to keep "optional keys" at a minimum.

Depending on the language, `a.b && ...` could be checking either or both of
the following:

\- does `a` have key 'b'? \- is `a.b` truthy?

~~~
jiofih
Tell that to the team that created protocol buffers.

------
m00dy
optional chaining !!! FTW

