
TypeScript 3.7: The Biggest Features and How to Use Them - based2
https://httptoolkit.tech/blog/5-big-features-of-typescript-3.7/
======
jdm2212
If you're too impatient to wait for first-class optional chaining in TS,
there's a nice open-source library for it that's been around for a little
while:

Repo: [https://github.com/rimeto/ts-optchain](https://github.com/rimeto/ts-
optchain)

Blog post with some details: [https://medium.com/inside-rimeto/optional-
chaining-in-typesc...](https://medium.com/inside-rimeto/optional-chaining-in-
typescript-622c3121f99b)

(I don't work for Rimeto, but a close friend did, which is how I stumbled on
that blog post.)

~~~
Shakahs
Hadn't seen this before, but I've been using a library from Facebook called
idx:

[https://github.com/facebookincubator/idx](https://github.com/facebookincubator/idx)

Idx is a bit more verbose because you have to write an arrow function for each
invocation, and it doesn't support default values.

------
nicoburns
The "Assert signatures" feature looks _excellent_. The biggest issue with
typescript has always been validating external inputs actually meet the type
contracts that your code says they do. With this, it looks like this could be
written as library!

~~~
joshAg
How do you verify it now? I've been using typeguards, but since i haven't
found a good way to generate interfaces from typeguard functions or typeguard
functions from interfaces I have to do each manually:

    
    
      interface ContactInfo {
        address_1: string;
        address_2?: string;
        city: string;
        state: string;
        zip: string;
        phone: number;
      }
      function isContactInfo(arg: any): arg is ContactInfo {
        let valid = false;
        const contactInfoFields: { readonly [key: string]: string[] } = {
          address_1: [ 'string', ],
          address_2: [ 'string', 'undefined' ],
          city: [ 'string', ],
          state: [ 'string', ],
          zip: [ 'string', ],
          phone: [ 'number' ],
        };
    
        if (typeof arg !== 'object') {
          return valid;
        }
        for (const key in contactInfoFields) {
          if(!contactInfoFields[key].includes(typeof arg[key]) || arg[key] === '' || Number.isNaN(arg[key])) {
            return valid;
          }
        }
        valid = true;
        return valid;
      }

~~~
frankpf
Not related to the new assert signatures feature (which is great!), but IMO
the two best approaches to do what you want today are:

\- io-ts[1]

This requires you to write your types as a runtime value, and allows you to
extract static types from those, e.g.:

    
    
        const ContactInfo = t.type({
           address_1: t.string,
           ...
        })
    
        type ContactInfo = t.TypeOf<typeof ContactInfo>
    

You can validate objects with `ContactInfo.decode(someObject)`

Note that we can have the same name for the type and value because they live
in different namespaces. When you do ContactInfo.decode, you're calling the
decode property of `const ContactInfo`. When you use `ContactInfo` in a type
position (e.g. `function x(arg: ContactInfo)`), you're using the `type
ContactInfo` declaration

\- typescript-is[2]

This uses TypeScript's transformer API. You can use it with
[https://github.com/cevek/ttypescript](https://github.com/cevek/ttypescript).
It generates validators for your interfaces/types/etc at compile-time.

[1]: [https://github.com/gcanti/io-ts](https://github.com/gcanti/io-ts)

[2]: [https://github.com/woutervh-/typescript-
is](https://github.com/woutervh-/typescript-is)

~~~
joshAg
typescript-is looks like it can be a drop-in solution since we're only dealing
with PODS. Thanks!

------
noncoml
My wishlist for Typescript is:

1\. Pattern matching switch against types(like Scala, Haskell, Ocaml)

2\. Input validation based on the already defined typescript interfaces

~~~
rictic
1\. Use discriminated union types:
[https://www.typescriptlang.org/docs/handbook/advanced-
types....](https://www.typescriptlang.org/docs/handbook/advanced-
types.html#discriminated-unions) \- TypeScript these days sticks with the
runtime semantics of JavaScript, and discriminated unions are a very natural
way to express algebraic data types in JS.

2\. Use [https://github.com/YousefED/typescript-json-
schema](https://github.com/YousefED/typescript-json-schema) to generate a JSON
schema, then use a json schema validator to do runtime validation. That's how
[https://github.com/Polymer/tachometer](https://github.com/Polymer/tachometer)
handles config file parsing and it works very well.

~~~
noncoml
My only problem with 1. is that it desn’t work that well with Error

~~~
azangru
Also, (1) won’t be exhaustive.

~~~
alangpierce
There are a few ways to get exhaustiveness checking in TypeScript when using
tagged unions. The way I usually do it is an assertNever function like this:

    
    
        function assertNever(value: never): any {
          return value;
        }
    

Then if you call assertNever on your variable in the default switch case or
the last else block, TypeScript will error if you didn't handle every case,
since it expects the variable to have been narrowed to the "never" type since
there's no remaining value that it can take on. That's also a good place to do
a runtime check since TS types aren't guaranteed to match runtime values.

------
ElFitz
This is really starting to remind me of Swift.

Coming from Swift, undefined and null handling always felt clumsy in both
Javascript and Typescript.

Glad I'll finally get my optionals and nil coalescing back; I've missed them
ever since I moved from iOS development to FaaS.

~~~
drenvuk
it feels like the new features for recent languages are starting to look the
same because they're nice. Kotlin has this stuff too. Rust and Kotlin have a
similar style of null handling.

~~~
hatfortguy
Point well made. I've spent some time with TS, Rust, and Kotlin recently and I
really enjoy how they all have these kinds of features. Really feels like they
see how well it works elsewhere and learn from one another.

------
drenvuk
I don't really care for typescript much but the optional chaining and null
coalescing for vanilla are very nice.

~~~
cstrat
Yeah I was going to say the same thing - love that optional chaining syntax...
Would cut down so many checks and balances needed to avoid those errors.

------
lf-non
Availability of recursive-types is a great news for users of libraries like
Mobx state tree [1] which heavily lean on inferred & derived types.

Circular type references among MST models have so far required quite a bit of
ceremony [2] to deal with. Really looking forward to get rid of that
boilerplate.

[1] [https://github.com/mobxjs/mobx-state-
tree](https://github.com/mobxjs/mobx-state-tree)

[2] [https://lorefnon.tech/2019/08/15/dealing-with-circular-
type-...](https://lorefnon.tech/2019/08/15/dealing-with-circular-type-
references-in-mobx-state-tree/)

------
no_wizard
These are all amazing features

I am really hoping for private properties and compiler support of class
properties (it supports the syntax, I think, but doesn't compile them down
from what I understand).

I also hope they update their decorator support to be in line with
[https://github.com/tc39/proposal-
decorators](https://github.com/tc39/proposal-decorators)

I know its stage 2 (and it was stage 3, I think) but I think the reasoning
behind the major(ish) changes are solid ones.

Thats pretty much it. Now tc39 just needs to acceept Reflect.metadata :)

------
based2
[https://www.reddit.com/r/programming/comments/d38rp9/typescr...](https://www.reddit.com/r/programming/comments/d38rp9/typescript_37_the_5_biggest_features_how_to_use/)

------
dugmartin
Nice to see optional chaining. It was the one feature I missed the most from
CoffeeScript. The null coalescing is also nice - I’ve been bitten more than
once with falsy values reverting to defaults on assignment.

------
gdsdfe
Anyone have some book or course recommendations for learning Typescript??

~~~
austincummings
The TypeScript Handbook [0] is where I've learned the most from. The New
Handbook [1] is starting to come together as well, it's not complete though.

[0]: [https://www.typescriptlang.org/docs/handbook/basic-
types.htm...](https://www.typescriptlang.org/docs/handbook/basic-types.html)

[1]: [https://microsoft.github.io/TypeScript-New-
Handbook/outline/](https://microsoft.github.io/TypeScript-New-
Handbook/outline/)

~~~
gdsdfe
that's pretty good actually, thanks!

------
hashkb
I may not be the sharpest, but isn't top level await just shoehorning
synchrony into a language that has been laughing at synchrony for decades?

~~~
lf-non
top level await doesn't make async operations synchronous.

It mostly eliminates the need to have immediately evaluated wrapper async
functions that we would have needed so far.

(async () => { await foo(); })();

The added benefit is that imported scripts would be implicitly awaited upon,
which has been clunky to do otherwise - you'd need to have a module that
exposes an async function and expect the consumer to await on them. But the
moment you do that you'd no longer be able to directly run the script through
node, so you'd end up needing one more file that imports this module and runs
it directly.

Availability of top-level await makes experimenting with (promise-returning)
APIs in REPL much easier. It is also a bit step forward in making typescript
more useful as a general purpose scripting language (outside webdev context).

~~~
hashkb
> top level await doesn't make async operations synchronous

No, it just lets us write them like they look in synchronous languages.

So we're jumping through even more hoops to avoid the realities of
asynchronous JS. IMO it's better for the asynchrony to be explicit. A whole
generation of frontend devs aren't going to have any idea how their code is
actually running.

------
cryptica
Does anyone know when TypeScript plans to introduce dynamic typing for
function/method parameters? It would be very useful if TypeScript could infer
the type of variables at runtime so that you never have to specify it.

~~~
matthewmacleod
I may have missed your point, but wouldn’t this be essentially useless? You
then have no type information about the parameters at all. Wouldn’t this just
be the same as the existing implicit “any” type when not in strict mode?

~~~
alangpierce
Strongly typed functional languages (including Reason) can often figure out a
function's parameter types based on how the variables are used in the
function. For example, given `(a, b) => a.push(b * 2)`, it could figure out
that `b` must be of type `number` and `a` must be of type `Array<number>`, so
the function author wouldn't need to write the type annotations.

I think it's likely that TypeScript will never implement this (at least not at
the level of sophistication of typical functional languages), given that it
adds a lot of complexity to the language, and making types explicit at
boundaries is usually good practice anyway.

~~~
lstamour
It's arguable that they might, actually, add this in the future, but ... it
would probably show up as part of how you can use TypeScript to type-check
your JavaScript code such as when it infers types from JSDoc.

