TypeScript Version: 3.7.0-dev.20191002
Search Terms: style display null
Code
document.body.style.display = null;
Expected behavior: should compile as in previous versions
Actual behavior: complains about null not a valid type with compiler option strictNullChecks
Playground Link: https://www.typescriptlang.org/play/?ts=Nightly#code/CYewxgrgtgpgdgFwHQCMTAJ5IM4IwGxiWAEtsAHfAQwwAIBeWuCffAbgCgg (playground is working)
Related Issues: -
Related to https://github.com/microsoft/TypeScript/issues/2521. Typescript doesn't support different types for the getter and setter of a property. Since display is always string on get, and setting with null is identical to setting with "", is there much a point to having null on the type? I personally would rather have a type of string and so not need to do assertions or pointless null checks when reading the value.
I see. So the reason for this change is a design limitation of TypeScript in covering valid JavaScript. I do not understand the limitation though as there is already a differenciation between getter and setter, and also left hand expressions. The only missing part to completly distinguish between them is support of getter and setter in interfaces. Maybe that is something for TypeScript 4?
So the reason for this change
I should clarify that I don't know why it was changed; but the change makes sense to me as outlined above.
This was mentioned in the blog post as a breaking change: https://devblogs.microsoft.com/typescript/announcing-typescript-3-7-beta/
A lot of nulls were removed from the DOM APIs because they are incorrect. Just use an empty string.
Okay, thanks. I have somehow overlooked it.
Working as Intended
@bre1470 would you consider re-opening this? The "nullability checks" breaking change from the 3.7 release notes doesn't give any sort of justification for why it was made. The relevant spec does say to "treat null as the empty string", but that just means that null should be valid for assignment to CSS properties. The only reason I can imagine to break existing code like this is because of #2521, so if that issue ever gets resolved then it's quite possible that this change should be rolled back.
@thw0rted Yes, I can do that. The workaround is to use the setProperty function as described in the linked specs. So the TypeScript library is not working completly outside of it - just for the named properties.
null -> "" is the sort of implicit coercion that's disallowed nearly everywhere else in the language. You can set arr.length = null too at runtime to empty out an array, but this is considered to be "wrong" compared to setting arr.length = 0.
A reasonable principle is that following o.p = x, o.p === x should be true for any "valid" x.
I think this is just going to wind up re-hashing the whole discussion at #2521 -- yes, o.p = x; o.p === x "should" be true, in some moral-imperative sense of "should", but for a big chunk of the DOM API, and presumably a large amount of legacy JS code, it isn't.
Would I like if everybody stopped using setter type coercion to "helpfully" allow conversion at time of assignment? Yes. Would I like to be able to describe the shape of libraries that use this convention anyway accurately in Typescript? Also, yes.
I agree with @thw0rted, that TypeScript should provide all the tools to describe the JS specification in its full meaning, even if things are questionable. JS allows type-indifferent getter and setter, and whether that is a reasonable principle or not, should be up to TypeScript users to answer.
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.
Most helpful comment
I think this is just going to wind up re-hashing the whole discussion at #2521 -- yes,
o.p = x; o.p === x"should" be true, in some moral-imperative sense of "should", but for a big chunk of the DOM API, and presumably a large amount of legacy JS code, it isn't.Would I like if everybody stopped using setter type coercion to "helpfully" allow conversion at time of assignment? Yes. Would I like to be able to describe the shape of libraries that use this convention anyway accurately in Typescript? Also, yes.