-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Guidelines for choosing between null
and undefined
with strictNullChecks
#9653
Comments
Please see #7426 for relevant discussion. |
Ok, thanks! |
One thing to note is that "optional" is really
Without going into ideological arguments, might be worth watching Douglas Crockford's video when he talks about this in details; the main issue is most programming language use one value to indicate what The TS compiler internally opted to use only If you want to use both |
Thanks for the clear TL;DR. I suppose at some point in #7426 the syntax T? was discarded but is hard to find. Only using Probably |
@olmobrutall huge thread but see #7426 (comment) |
There it is :) |
In my quest to use
let error: { [member: string]: string } there is always going to be some key for witch you won't have a value... |
I'm not aware of any reference .d.ts files yet. We decided to make indexers not introduce |
Is there an issue where this was discussed? I think this is not the right decision: While using What make sense for me is that if the return type of the indexer is T means that the values that you can encounter when the key is there will be T, or what is the same, the return type of But when you acces the object using the indexer, Object.keys(errors).map(k=>errors[k]!); Is there any argument agains it? |
The expression Object.keys(errors).map(k => errors[k]) has type |
If indexers contained undefined every array access a[i] would be T | undefined. This is very annoying and would be borderline unusable. |
If you were indexing by the wrong key, adding the |
Well, As any casting the compiler asks the developer to pay special attention to a potentially unsafe action, and in exchange the compiler trust the developer criteria. Using an indexer is unsafe, because independently of the declared return type, potentially you'll get back some Example: const cache :{ [v: number] : number} = {};
function fib(v : number){
if(v <= 1) return v;
const c = cache[v];
if(c != undefined)
return c;
return cache[v] = fib(v-1) + fib(v-2)
} I think it's obvious that the type of Also the Something different is that this would be annoying in many other practical examples, but I suppose I have now a thicker skin after my quest to enable Just after turning the flag on, I've found 800 errors in a ~50 files project, of witch I've solved until now 600 (two evenings). The investment necessary to introduce the flag is quite high. I was expecting something like 4 compile-time errors for each potential run-time bug fund.... but it's more like 50, and what is worst, the way to solve most of them is by adding Here are some things that are creating me pain :
JSON.stringify({}) //"{}"
JSON.stringify({ name: undefined }) //"{}"
JSON.stringify({ name: null }) //"{"name":null}" For me this has important consequences, since in one case the property in the server side will be ignored (
Sorry for my long rant, I'm a very enthusiastic Typescript and C# developer and I had lots of hopes in non-nullable references. I also develop the framework in my free time. If I consider this a tough pill to swallow, I can not imagine in a more enterprise environment... What's even worst, I think there is not too much that Typescript or any language that deals with the real world can do to solve the problem once and for all... looks to me that there are lots of variables that are nullable only in 5% of the cases, so the compiler gets a lot on the way to provide little help. |
After 2 months of working with not-nullable types I want to re-evaluate my opinion. The transition was a hard, forcing you to re-architect parts of the application and be more careful about nullability (expected) and the subtle differences between null and undefined (unexpected) but I'm very satisfied with the end result. Thanks for the great work! PD: Maybe you can forward this to C# team to give them some courage for the next version ;P |
@olmobrutall the C# team is definitely considering this. There is an extensive proposal and a lot of discussion around the issue of non-nullable types. Check it out dotnet/roslyn#5032 |
I know, I've been very active in this thread and in the previous one in Codeplex, but it has been delayed for C# 8 :S |
For future readers, this isn't quite true. You can't define an interface with a property |
@MicahZoltu there is a syntactic sugar for that interface I {
name?: Type;
} It is a little inconsistent, probably because that notation predates |
@aluanhaddad Sorry I wasn't more clear, that is what I meant . Will edit my comment. |
I see now what you meant. My take on it is that, even though what you say is technically correct, |
Whenever you want to make a type optional you have to choose what value to use for the missing values:
| undefined
.| null
.*T?
is not introduced as equivalent toT | null | undefined
. BTW this example is misleading.In my opinion for most of the cases the distinction is useless as long as you use non-strict comparison (
==
.=!
) and boolean operators (&&
||
).Unfortunately writing
| null | undefined
is way too cumbersome, specially if you need have more than one optional thing in a type expression.This is a real case:
Promise<Array<T | null | undefined> | null | undefined> | null | undefined
Some recomendations?
The text was updated successfully, but these errors were encountered: