-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Suggestion: non-nullable type #185
Comments
I suggest using a type other than string as an example since it by nature is nullable. :P
And because it's defined as non-null, everything might be happy for the compiler, but then someone else who uses it in javascript passes something null and kaboom. Now that said, maybe the solution could be that for public facing methods, it could automatically assert not null. But then the compiler could also assert that you cannot have public properties (or private for that matter really) that can have a !nonnull declaration since they could not be enforced. This may go deeper into the discussion of code contracts for this to be properly enforced. |
Forgive my critics, I think there is very little need in non-nullable types if/as-soon-as algebraic data types are here. The reason people use |
Personally, I just wrote a little |
I don't really understand you can also define : function myFunc(str: string): int {
return str && str.length;
} and if someone pass an |
With union types, we could have a pretty simpler specification for that. var myNullableString: (null | string);
var myString = "hello";
myNullableString = myString //valid
myString = myNullableString // error null is not assignable to string; With the 'strict mode' activated typescript should check that every variable non nullable is initialized, also by default optional parameter are nullable. var myString: string; // error
var myNullableString: (null | string); // no error
function myString(param1: string, param2?: string) {
// param1 is string
// param2 is (null | string)
} |
IIRC from what Facebook showed of Flow which is using TypeScript syntax but with non-nullable types by default they support a shorthand for |
That could potentially be quite annoying in the case where you want to initialize a variable conditionally, eg.:
In Rust for example, this is fine as long as the compiler can see that myString will get initialized before it is used but TypeScript's inference doesn't support this at the moment. |
Honestly doing something like |
@fdecampredon +1 for this - I like the idea very much. For code bases that are 100% JavaScript this would be a useful compile-time only constraint. (As I understand your proposal there's no intention for generated code to enforce this?) |
As for shorthand for |
Sum types make non-nullable types by default a very interesting possibility. The safety properties of non-nullable by default can't be overstated. Sum types plus the planned "if/typeof destructuring" (not sure what this should be called) even make it type safe to integrate nullable and non-nullable APIs. However, making types non-nullable by default is a huge breaking change, which would require changing almost every existing third-party type definition file. While I am 100% for the breaking change, no one person is able to update the type definitions that are out there in the wild. It's good that a great consensus of these definitions are collected in the DefinitelyTyped repo, but I still have practical concerns about this feature. |
@samwgoldman the idea is to have non-nullable types only under a special compiler flag like |
@fdecampredon What about the type definitions for non-TypeScript libraries, like those at DefinitelyTyped? Those definitions are not checked by the compiler, so any 3rd party code that could return null would need to be re-annotated in order to work correctly. I can imagine a type definition for a function that is currently annotated as "returns string," but sometimes returns null. If I depended on that function in my Unless I'm missing something, I don't think this is functionality that can be turned on and off with a flag. It seems to me that this is an all-or-nothing semantic change to ensure interoperability. I would be happy to be proven wrong, though, because I think a flag-switched feature is more likely to happen. As an aside, there isn't much information available yet on Facebook's Flow compiler, but from the video recording of the presentation, it seems like they went with non-nullable by default. If so, at least there is some precedence here. |
Ok let's assume there is a shorthand
I don't see the problem, sure some definition files won't be valid with the
I don't see why we could not have a flag switched feature, the rules would be simple :
Where is the incompatibility with a flag-switched feature ? |
Flags that change the semantics of a language are a dangerous thing. One problem is that the effects are potentially very non-local: function fn(x: string): number;
function fn(x: number|null): string;
function foo() {
return fn(null);
}
var x = foo(); // x: number or x: string? It's important that someone looking at a piece of code can "follow along" with the type system and understand the inferences that are being made. If we starting having a bunch of flags that change the rules of the language, this becomes impossible. The only safe sort of thing to do is to keep the semantics of assignability the same and change what's an error vs what isn't depending on a flag, much like how |
I know it would break retro-compatibility, an I understand @RyanCavanaugh point of view, but after tasting that with flowtype it is honestly really an invaluable feature, I hope it will ends up being a part of typescript |
In addition to RyanCavanaugh's comment --> From what I read somewhere, the ES7 specification / proposal mention the use of function overloading (Same function name but different input parameter datatype). That is a very sorely needed feature for Javascript. |
From the flow docs:
var o = null;
print(o.x); // Error: Property cannot be accessed on possibly null value
var o: ?string = null;
print(o.length); // Error: Property cannot be accessed on possibly null or undefined value
(i.e. in TS lingo understands type guards) var o: ?string = null;
if (o == null) {
o = 'hello';
}
print(o.length); // Okay, because of the null check Limitations
|
What if the option is added at the same time when introducing the |
@jbondc seems good. however the problem with that is that it will ends up with |
What does this mean? There are no static types in js. So, yes, strings are "nullable", but let's not forget that they are also numberable and objectable and fooable, etc. Any value can have any type. So when layering a static type system on top of javascript, choosing whether static types are nullable or not is just a design decision. It seems to me non-nullable types are a better default, because it's usually only in special cases that you want a function signature, for instance, to accept a null value in addition to the type specified. |
Directives like "use strict" that cause scoped changes to semantics are already a part of the language; I think it would be reasonable to have a "use nonnullable types" directive in TypeScript. |
@metaweta I don't think it's enough, for example what happens if a non null module consume a nullable one : //module A
export function getData(): string[] {
return null;
}
//module B
'use nonnull'
import A = require('./A');
var data: string[] = A.getData();
|
Yes, var data: string[] = A.getData(); would cause an error. Instead, you'd have to provide a default value for when var data: string[] = A.getData() || []; |
@metaweta ok but how do you know that it's an error ? :) |
Yes, exactly (unless a type from the nullable module is explicitly marked otherwise). |
I attempted to mitigate this problem with a special type |
+1 for --noImplicitNull as well PLEASE 👍 |
+1 for --noImplicitNull |
Should this be closed? |
@isiahmeadows It would probably be better to leave this open then. |
We think #2388 is the renaming part of this work. This is why we have not declared this feature complete yet.
I am not sure i understand what is requested semantics of this new flag. i would recommend opening a new issue with a clear proposal. |
@mhegazy The idea posited earlier in this issue for |
Sorry if I comment on a closed issue but I don't know a better place where to ask and I don't think this is worth a new issue if there's no interest. |
@massimiliano-mantione, please see #8405 |
Introduce two new syntax for type declaration based on JSDoc
by default type are nullable.
Two new compiler flag :
inferNonNullableType
make the compiler infer non-nullable type :nonNullableTypeByDefault
(I guess there might be a better name) :The text was updated successfully, but these errors were encountered: