-
Notifications
You must be signed in to change notification settings - Fork 13.2k
Add nullability annotations to core.d.ts and es6.d.ts #7650
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
Conversation
src/lib/es6.d.ts
Outdated
| * @param source The source object from which to copy properties. | ||
| */ | ||
| assign<T, U>(target: T, source: U): T & U; | ||
| assign<T, U>(target: T, source: U | null | undefined): T & U; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This (and similar for the overloads below) is needed because null and undefined are allowed and ignored by Object.assign, but the compiler should not infer U as null if null is passed in, as the result T & null is meaningless.
Should I add a comment to that effect?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, on closer look it seems U is still specialized as null instead of {}. But also the resulting type T & null doesn't seem to have any issues either.
Should I remove the | null | undefined from this function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
T & null and T & undefined should not be a problem, because null and undefined add no new member to the type? In fact, I think the type system could (should?) simplify T & null & undefined to just T.
If it were T | null that would be a real problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW I don't think Object.assign is "meant" to explicitely accept undefined. It reflects the fact the the parameter is optional and that should probably be modelled with assign<T>(target: T): T, so that you can call assign(x); or maybe assign<T, U>(target: T, source?: U).
Note that removing null and undefined from being explicit in the signature doesn't change the fact that assign(x, null) is still valid.
Of course the right thing to do here would be variadics (2.1) since the real signature is assign<T, ...U>(target: T, ...source: ...U): T & ...U.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
T & nullandT & undefinedshould not be a problem, becausenullandundefinedadd no new member to the type?
Yes, it appears so, but...
In fact, I think the type system could (should?) simplify
T & null & undefinedto justT.
It doesn't, hence my initial concern that this would be problematic. But it seems to be fine regardless, in that the instances of T & null appear to be usable as T everywhere. I'm waiting for the TS team to confirm / deny if this is expected behavior or a bug.
BTW I don't think
Object.assignis "meant" to explicitely acceptundefined.
Yes, this is what I thought as well. I'm not familiar with all of assign's uses, so if it's not expected that users will want to use it with null / undefined sources then it would be nice to have a way to specify that U can't be null. Perhaps U extends {} ? I'm not in front of tsc to try at the moment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is brand new stuff, maybe @ahejlsberg should add a reduction rule from T | null | undefined to T... that may simplify a few other places where this might come up?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do not think this is the correct change here. the current signature declaration is better. i think what you want is a type operator like the expression operator ! (which does not exist) on the return type to indicate that null and undefined are ignored. e.g. assign<T, U>(target: T, source: U): T! & U!;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reverted.
| * predicate. If it is not provided, undefined is used instead. | ||
| */ | ||
| findIndex(predicate: (value: number) => boolean, thisArg?: any): number; | ||
| findIndex(predicate: (value: number) => boolean, thisArg?: any): number | undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
predicate is incorrect, it should be the same as for find().
See https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/TypedArray/findIndex
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Arnavion feel free to send a separate PR for the predicate changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mhegazy And should I move the other commits after the first one into a separate PR as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On a second thought, the commit messages look clear enough, so feel free to include the findIndex chances in this PR if you like or have it in a separate one. up to you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've removed them from this PR. Will make another one.
|
thanks! |
|
The other changes are in #7664 |
|
|
||
| // Non-standard extensions | ||
| compile(): RegExp; | ||
| compile(): this; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think there is a guarantee that compile returns your subclass if you subclass RegExp, so it should return plain RegExp instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to ES specs it should return the this value of the compile() call.
So using this type here seems like the correct thing to do.
BTW: this method is deprecated so hopefully it won't matter much.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concur 👍
| nulland| undefinedwhere appropriate.| undefined. I have added it to the ES6 collection accessors likeMap.gethowever. I think that's better.| nullor| undefinedto functions that stringify their parameter and thus acceptnullandundefined, egSymbol(null)is the same asSymbol("null"). It doesn't seem right to allownulljust for that.1. ES6's String.normalize'sformparameter was typed as string - changed to union of string literals.1. Map and Set methods that are specced to returnthiswere not annotated as: this, changed accordingly.I can split the changes into separate PRs if you want. I just fixed them as I came across them while doing the first one.The other changes became too big and will be in another PR.
jake runtestspasses.