-
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
Strict optional properties #43947
Strict optional properties #43947
Conversation
@typescript-bot pack this |
Heya @ahejlsberg, I've started to run the tarball bundle task on this PR at a01fd4f. You can monitor the build here. |
@typescript-bot test this |
Heya @ahejlsberg, I've started to run the parallelized Definitely Typed test suite on this PR at a01fd4f. You can monitor the build here. |
Heya @ahejlsberg, I've started to run the extended test suite on this PR at a01fd4f. You can monitor the build here. |
Heya @ahejlsberg, I've started to run the perf test suite on this PR at a01fd4f. You can monitor the build here. Update: The results are in! |
Heya @ahejlsberg, I've started to run the parallelized community code test suite on this PR at a01fd4f. You can monitor the build here. |
Hey @ahejlsberg, I've packed this into an installable tgz. You can install it for testing by referencing it in your
and then running |
@ahejlsberg Here they are:Comparison Report - master..43947
System
Hosts
Scenarios
Developer Information: |
I'm getting unexpected type information when playing around with this example from the linked issue. Does this require further work in the language server to rectify? I'd expect for the type of type InputProps = {
foo?: string;
bar: string;
}
// Hover over foo here
const inputProps: InputProps = { foo: undefined, bar: 'bar' }; |
The user suite test run you requested has finished and failed. I've opened a PR with the baseline diff from master. |
I love the change and couldn't be happier about it ❤️ I have a minor question/concern though: what about types coming from external dependencies? narrowing down based on the |
@tom-sherman In the new |
Also think about definitely typed. I don't think anyone is going to individually verify that every js implementation will obey the new strict version of Edit: maybe that is a bit over dramatic |
@ahejlsberg I expected this example would now compile but it doesn't seem to unfortunately. Do you know why that is? type Dict<T> = { [key: string]: T };
interface F extends Dict<string> {
// Property 'foo' of type 'string | undefined' is not assignable to string index type 'string'.
foo?: string;
} |
Excited about this option and glad to see it officially in TS 4.4 :-) Just a suggestion for docs, that you may want to remind people they can use the delete operator to remove a property (since exactOptionalPropertyTypes of course means you can't set it undefined). I feel like a lot of people probably don't know about this operator - or need reminding about it if they're accustomed to setting things undefined. I think it would be important to mention in any documentation on this new flag.
Instead, to clear the property with the
Caveat: At this point in time this gives an error (playground link) which I'm assuming is a temporary issue? Also: Despite the URL parameter in this playground link, you must manually enable |
@simeyla maybe that's a suggestion worth bringing into @sandersn's change at #45032. When directly assigning On the other hand, I don't know how much we recommend that pattern in the first place, and we might be more inclined to tell users to add Edit: regarding your caveat, just try it out in a nightly version. There is not a second bug, |
@simeyla Actually, can you open a second bug? #45032 covers a slightly different error (values with properties that are undefined) and is pretty big already. Just copy your example into a new bug -- it captures the request precisely. At that point we can decide whether to handle it in the same codefix or not. |
|
I see in the source code the following related intrinsic types being used:
Ah! The
Actually
produces, through the API |
Thanks for the strictOptionalProperties, but it seems to me now that it leads to a lot of redundancy that looks like This happens because the authors of the libraries have no clue about the state of the strictOptionalProperties in the project that uses it, therefore they assume "the worst" (which is strictOptionalProperties: true) and have to write The problem is that in the most popular scenario, which is when people don't care about whether I don't know what were the alternatives. If the only problem was an impossibility to say "the field may not exist, but must not be undefined" (is there any "real" situation when people actually needed it, by the way? not Foo?), then |
TypeScript has no way to represent a "not"-type. This would require #29317. |
@kokushkin that's the consequence of adding TS features that were never intented to be present in the language. People pushed for this one and |
@kokushkin - It's worth pointing out that the change (1) didn't break existing (without the "strictOptionalProperties") setups, (2) the .d.ts files can, and probably were, changed progmaticaly with a script, and (3) without the change some native javascript scenarios simply could not be represented in Typescript, fundamentally hobbling Typescript. Apart from the readability issue (which IMO is not a problem), the only problem is old apps without "strictOptionalProperties" being extended to use new libs with "strictOptionalProperties", because the app could try to pass a disallowed "undefined" to a lib that doesn't accept it, and there would be no UI warning. (I am guessing there is no warning). If so, then maybe information could be placed in the .d.ts file to inform that it is assuming "strictOptionalProperties", and typescript could generate a warning for case of app with "strictOptionalProperties:false" and libs with "strictOptionalProperties:true". |
Hi, I'm coming here from the docs and I'm not sure about the value of this property. It seems to be "true | false | undefined" but it's not stated clearly in the doc: https://www.typescriptlang.org/tsconfig#exactOptionalPropertyTypes Also which is the strictest option? Is it "true" ? |
It defaults to false and if u want this strict behavior then u can opt into it using true |
Hi, I tried |
@Kay-Yuan That's an issue with Angular and should be addressed there. TypeScript has nothing to do with .html files. |
Thanks a lot! Just not sure which part of the error belong. I will comment this to Angular. Cheers. |
With this PR we introduce a new strict mode,
--strictOptionalProperties
, in which optional properties declared without an explicitundefined
in their type do not permit assigning a possiblyundefined
value. This makes it possible to ensure that optional properties are neverundefined
when they're present on an object, and thatundefined
values read from optional properties unequivocally indicate that the properties are not present. The new compiler switch is in the--strict
family of switches and this PR is therefore a breaking change for code compiled in--strict
mode (unless, of course, the switch is explicitly set tofalse
).In
--strictOptionalProperties
mode, assigningundefined
toobj.a
is considered an error because the declared type ofa
doesn't explicitly includeundefined
. However, when readingobj.a
the type is stillstring | undefined
to account for the possibility that the object doesn't have ana
property.The
b
property above explicitly includesundefined
in its type and is thus unaffected by--strictOptionalProperties
.In
--strictOptionalProperties
mode, for an optional property declared withoutundefined
in its type, control flow analysis accepts thein
operator and thehasOwnProperties
method as proof that the property is present, and consequently excludesundefined
from the property value.Note above that
obj.a
is not assignable to itself unless it is guarded by a check that the property is present. While initially surprising, this makes sense because, if the property is not present, it would become present with the valueundefined
following the assignment.In
--strictOptionalProperties
mode, thePartial<T>
utility type produces strictly checked optional properties as expected. For example:In
--strictOptionalProperties
mode, optional elements in tuple types are strictly checked when they don't explicitly includeundefined
in their type. For example:Fixes #13195.