www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Things I found great about TypeScript that D could benefit from

reply w0rp <devw0rp gmail.com> writes:
Hello everyone! I haven't written a post in a long time. I love 
D, and I've been a D hobbyist for years now. Though I haven't 
written any D in a long time, I keep an eye on the changelogs and 
such. More recently I've been using TypeScript (TS) at work for 
front end code. TypeScript is a very different kind of beast, 
compared to D, but there are some features in TypeScript I now 
use every working day which have really improved the quality of 
the software that I write, and I'd like to share my thoughts on 
them. I'll explain a few things and then say what I think D could 
learn from TS.

The first feature I found really useful is the --strictNullChecks 
option that TypeScript has. I hate null dereferencing errors with 
a passion, and they have been the number one source of bugs that 
I've seen. The TS type system with the option off effectively 
treats `T` as `T | null | undefined` with the option off, and 
excludes `null | undefined` with the option on, meaning it forces 
you to check for `null` or `undefined` where such values are 
possible, according to the type system.

What I found really interesting is that TS implements null 
checking not through more traditional means like a "Maybe" or 
"Option" monad, but through typical syntax. If you write `if (x 
!= null) { }`, then TS narrows the type from `T | null | 
undefined` to just `T` inside of that if statement. This also 
works for more complex syntax, such as breaking a loop, returning 
early if something is null and pressing on if it isn't, inside 
expressions like `x != null && x.y`, and so on. I could never get 
colleagues on board with changing all of their code to use 
Maybe/Option types, but this kind of syntax is something they 
don't even have to think about.

The second feature I found very useful is that TS uses 
"structural typing." You declare an interface with some 
properties, and any object which matches those properties is 
considered to be of that type. Meaning that TS doesn't care what 
the "class" or prototype of your object is, just that has the 
right stuff in it. This is essentially statically-checked duck 
typing. There is some algebra on types, so you can write `T & U` 
for something with the properties of types `T` and `U`, or `T | 
U` for either.

What's very powerful about unions in TypeScript is that it 
automatically determines which fields can be used as tag 
attributes for tagged unions. This means you can declare tagged 
unions without thinking about writing a very specific tagged 
union type, and without using a special tagged union type. This 
largely works because of the nature of TS's basis on top of a 
dynamic type system where attribute lookup is all virtual.

The third big feature I'll end on is just the quality of the 
tooling. There's great code completion, tools for fixing bugs, 
pretty good diagnostics, a protocol like LSP I integrated into 
Vim, etc. They have done a pretty good job of getting the tools 
right.

What I think D could learn is pretty much...

* Strict null checking is a winner, and you can use ordinary 
syntax to handle this.
* Writing `(InputRange r)` instead of `(T)(T r) if 
(isInputRange!T)` would be a nice improvement, and writing 
something like this hypothetical `InputRange` concept could be a 
lot easier, somehow. (C++20 might finally include concepts.)
* Good tooling makes everything better. Keep on working on good 
tools for D.

That's it, let me know your thoughts.
Apr 27 2018
next sibling parent Mark <smarksc gmail.com> writes:
On Friday, 27 April 2018 at 19:17:14 UTC, w0rp wrote:
 * Writing `(InputRange r)` instead of `(T)(T r) if 
 (isInputRange!T)` would be a nice improvement, and writing 
 something like this hypothetical `InputRange` concept could be 
 a lot easier, somehow. (C++20 might finally include concepts.)
There was a discussion of this here: https://forum.dlang.org/post/oju39p$1il3$1 digitalmars.com
Apr 27 2018
prev sibling next sibling parent rikki cattermole <rikki cattermole.co.nz> writes:
On 28/04/2018 7:17 AM, w0rp wrote:
 Hello everyone! I haven't written a post in a long time. I love D, and 
 I've been a D hobbyist for years now. Though I haven't written any D in 
 a long time, I keep an eye on the changelogs and such. More recently 
 I've been using TypeScript (TS) at work for front end code. TypeScript 
 is a very different kind of beast, compared to D, but there are some 
 features in TypeScript I now use every working day which have really 
 improved the quality of the software that I write, and I'd like to share 
 my thoughts on them. I'll explain a few things and then say what I think 
 D could learn from TS.
 
 The first feature I found really useful is the --strictNullChecks option 
 that TypeScript has. I hate null dereferencing errors with a passion, 
 and they have been the number one source of bugs that I've seen. The TS 
 type system with the option off effectively treats `T` as `T | null | 
 undefined` with the option off, and excludes `null | undefined` with the 
 option on, meaning it forces you to check for `null` or `undefined` 
 where such values are possible, according to the type system.
 
 What I found really interesting is that TS implements null checking not 
 through more traditional means like a "Maybe" or "Option" monad, but 
 through typical syntax. If you write `if (x != null) { }`, then TS 
 narrows the type from `T | null | undefined` to just `T` inside of that 
 if statement. This also works for more complex syntax, such as breaking 
 a loop, returning early if something is null and pressing on if it 
 isn't, inside expressions like `x != null && x.y`, and so on. I could 
 never get colleagues on board with changing all of their code to use 
 Maybe/Option types, but this kind of syntax is something they don't even 
 have to think about.
 
 The second feature I found very useful is that TS uses "structural 
 typing." You declare an interface with some properties, and any object 
 which matches those properties is considered to be of that type. Meaning 
 that TS doesn't care what the "class" or prototype of your object is, 
 just that has the right stuff in it. This is essentially 
 statically-checked duck typing. There is some algebra on types, so you 
 can write `T & U` for something with the properties of types `T` and 
 `U`, or `T | U` for either.
Signatures, I've got a DIP for this. Only this is a pretty basic feature of it.
Apr 27 2018
prev sibling parent SimonN <eiderdaus gmail.com> writes:
On Friday, 27 April 2018 at 19:17:14 UTC, w0rp wrote:
 The first feature I found really useful is the 
 --strictNullChecks option that TypeScript has. I hate null 
 dereferencing errors with a passion, and they have been the 
 number one source of bugs that I've seen.
 * Strict null checking is a winner, and you can use ordinary 
 syntax to handle this.
 That's it, let me know your thoughts.
we don't have to worry about null-or-not, we have our mind free for the interesting problems. I love to peek around other languages and see how they tackle this problem. Thanks for the TS overview! You advocate automatic narrowing inside if (x != null) even over Optional types. Is it because you find automatic narrowing cleaner than Optional? Or do you simply consider automatic narrowing a worthwhile addition whether or not a language has non-null + Optional? ``` void f(Optional!T x) { if (x !is null) g(x); } void g(T x) { h(x); } void h(T x) { writeln(x.myField); } ``` With a strictly non-nullable T, you can write `g` and `h` cleanly and null-safely. Without non-nullable types, even with implicit narrowing, both `g` and `h` would need an if/get or optional dispatch, complicating their definition. -- Simon
Apr 28 2018