Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Non-nullable types for TypeScript (github.com/microsoft)
185 points by muraiki on March 21, 2016 | hide | past | favorite | 32 comments


Too bad that "strictNullChecks" is not the default behaviour. Because this is the only really sane default, and is one the the things I loved so much in strongly types languages such as OCaml, F# or Haskell. It reduces so make case distinctions (and forgotten if/switch checks) to the only places where these are really used.

Also, "strictNullChecks" is kind of optional security, which is almost always a bad idea in the long run.

Maybe they did this for backwards compatibility? Are there any plans to make "strictNullChecks" the default in the future?


Since this is a brand new feature that isn't even accepted into the language yet, it obviously can't be made default. If they decide to make it the default behavior, there would need to be a period where the old bahavior is depreciated and triggers warnings, but not errors.

I hope the --noImplicitAny option will become default.


One of the most touted features is "your JavaScript is already valid TypeScript" (or pretty close), so I think they will keep the defaults so that JS developers can just change the .js to .ts and be up and running with as little friction as possible.


Well, with the last release, typescriot supposedly can compile plain js.

https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in...

That should make it simple to treat ts more strict than js.


> Well, with the last release, typescriot supposedly can compile plain js.

How does the ability to compile plain JS alter its goal of being a JS superset?


Because it can compile plain JS using the rules present under plain JS, such as nullable and undefined-able types by default, regardless of the rules it's using to compile TS.


It will never be the default, but its not a big deal as you can set it up in the project configuration options.

Not sure why the default matters at all. The idea behind TS is to be able to gradually turn up the strictness dial as you migrate from JS


Yes but the ideal would be to know that if its extensions ends with .ts then it's strict, if it's .js then it still is crap.


Typescript leans in the direction for increasing strictness one flag at a time in a project, which is particularly fair if you're migrating a legacy project but not always the most sane option for new projects.

In this case, too, there's a maintenance burden in that probably a bunch of type definitions files may need updating before this new strictness is usable in some projects. So there's a direct backward compatibility issue with existing Typescript code that will need to be addressed for this new strictness.

One of the proposals I've seen in the GitHub issues is that Typescript should at least offer a "Maximum Strictness" option that turns on all of the optional strictness checks together, which would be great for fresh projects, with the assumption that new versions of Typescript present some maintenance requirements for those projects. I would love to see that added to Typescript.


It would break Typescript backward compatibility. Making it optional was the right thing to do.


Languages like Haskell can get away with it because everything is statically compiled. But what would this look like for an environment like JS, that dynamically links against the user's browser? The user's browser may be older or newer, and expose different properties. Should every browser API be potentially nullable?


Potentially null features should be nullable and when not, it'll be a potential run-time error.


That's no different than any other TS code having to interact with regular JS.


The Google Closure type system is much saner on this front already. A variable of a declared type cannot be undefined. Nullable and non-nullable types are distinct: primitives are non-nullable by default, with an option to make them nullable (?string, ?number, etc.), and types deriving from Object are nullable by default, with an option to make them non-nullable (!Object, !MyType, etc.)

Of course JavaScript itself does not have a notion of nullable types, so touching any native API interfaces naturally leaves you with a bunch of nullable types where you may well know the value will never be null, so you are left trying to decide where to do nothing, where to add an assertion, and where to add a conditional branch. This ambiguity comes through the Closure API in many places that it would be nice to have a non-nullable type guarantee, but I suppose the library has evolved over time and further must be adaptable to a range of coding styles.


Google Closure is one of those things that is amazing when you realize all of the features it has. It just has 2 glaring problems:

1) It's written in Java which makes it a hassle to use in the typical front-end project setup.

2) The documentation is just atrocious.


> touching any native API interfaces naturally leaves you with a bunch of nullable types where you may well know the value will never be null

If a native API really never returns null it can be declared as such in Closure's externs (equivalent of a header file). If it can return null then doing a routine null check will automatically add the non-nullable attribute when the check succeeds, no cast required.


> and types deriving from Object are nullable by default

So what's the point then?


You can flip the default. Back when I was using Closure Compiler, it was the expected convention on my team to mark most of your type annotations non-nullable.


you mean value types rather than primitives right? (Strings are objects)

It would be saner if everything was non null by default. There'd be no need for a ! then and no ambiguity for beginners around whether something is nullable or not. No downside for non-beginners either unless they're in the habit of using more nullable parameters/vars than non-nullable, which doesn't seem like a particularly good idea...


Yes, value types, thank you.

Agreed on the defaults, although you then have the problem of reconciling with the native JS type system. I'm unclear on what this PR does to address that for TS - in strict null check mode, can an e.g. Node be null by default? If so, does the native "Node" object then become "Node|null"? At some level this has to be addressed.


There is no native type system.

Native objects can never be null. If its an object, it already isnt null. Functions,property accessors etc. can return Node or null or undefined, which can be modelled accordingly on a per-function basis


Thats not much saner, it would only be saner in Java. There are no “primitives” in JS.


I'm really impressed with how quickly the Typescript team is adding new features - it feels like every time I check in on them they have something new in the works that I really care about. Great work!


Looks like a good punch right into one of Facebook flow's advantages. Very glad to see both static typing alternatives for JS evolving.


> A type guard for a dotted name has no effect if any part of the dotted name is the target of an assignment within the guarded code. For example, a type guard for x.y.z will have no effect if the guarded code contains any assignments to x, x.y, or x.y.z.

This is interesting to me because it is:

1) Unnecessarily conservative.

    let x = { y: { z: intOrNull() } };
    if (x && x.y && x.y.z) {
        const z = x.y.z;
        x.y = null;
        // z is of type "number?" when it could be "number"
    }
2) Not sound w.r.t. aliasing.

    let x = { y: { z: intOrNull() } };
    let x_ = x;
    if (x && x.y && x.y.z) {
        x_.y.z = null;
        const z = x.y.z;
        // z is of type "number" with a value of "null"
    }


Really glad to see this. I encountered the use-before-declaration "feature" of TS, and I just assumed it was a bug, which I filed. I was flabbergasted when I was told it was by design, to match JavaScript.

The issue: https://github.com/Microsoft/TypeScript/issues/5822


Funny how the conclusion is basically "Don't use `var`, use `let` instead" - even though almost all documentation/examples exclusively use the `var` keyword!


From Ryan Cavanaugh's comment[1]:

> (...) there's already the let keyword available for those who want saner scoping rules. We should definitely update the docs to use let everywhere, though.

[1]: https://github.com/Microsoft/TypeScript/issues/5822#issuecom...


Yes, however that was 3 and a half months ago -- and as far as I can tell, there's been no movement towards doing so.


It's been fixed for a few months in the Handbook repo (https://github.com/Microsoft/TypeScript-Handbook/pull/119/fi...), but the new updated Handbook hasn't been pushed to the website yet.


Wow what a bunch of pedants! I completely agree with the issue you raised, I had a better consideration of the TS team.


I can only disagree and that thread gave me an excellent impression of the TS team[0]. They cleanly noted that this was expected behaviour, the reasoning behind it (which calls back to one of the underlying roles of typescript) and how to mitigate it. Can't say the same of your vote-spamming of every comment though.

[0] as someone mostly uninterested in TS




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: