-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
document.body should not require null check #4783
Comments
Why do you believe a null check shouldn't be required? Nothing in the SO link you provided suggests that should be the case. |
@jcready I dont want to write null checks. It's annoying. |
@Meai1 Then don't. If you don't want something checked there's I too had to learn this: Flow does not work by adding types on top of whatever Javascript code you use to write. It forces you to use - or to not use - certain constructs. After adding Flow you can only use a subset of Javascript code that is possible to write. That is intentional. |
@lll000111 As you can see from my example, I cant exactly add 'any' to document.body. It also defeats the purpose of static typing. |
@Meai1 Please read my short comment, I already answered that.
That too :-) |
To be clear, it is possible, however unlikely, for a document not to have a body. There are various (again, unlikely but possible) html documents that will do so. The official spec even says this property may return null. So flow is safe and follows this. Now, if you are sure it will be defined, you can just tell flow that by sssigning it to a variable and giving it a clearer type, perhaps any or at least an html element. But I feel pretty sure flow is not going to change its behavior so I’m going to close this issue. But you also asked how you could fork flow and code this yourself, which would be quite easy. The code you need to change is just this: https://github.com/facebook/flow/blob/master/lib/dom.js#L558 |
@asolove how do I change it so that the change gets picked up in nuclide? |
OK I put all the files from the folder you posted into a project folder called flow-typed, now it works! Thanks! |
For people coming here via Google: If you are writing an app where you know document.body will always exist, you can put the following content into a class DocumentWithBody extends Document {
// $FlowFixMe
body: HTMLBodyElement;
}
declare var document: DocumentWithBody; If you are writing a library, you should probably keep the null check, since you have fewer guarantees about where it will run. |
This is yet another Flow productivity-killer that could easily be added as a config option. As far as I know the document body can only be null if your script tag is in the Time and again I see issues like this one where Flow maintainers make impassioned arguments for the purity of the system, accusing users in not-so-many-words of being too lazy to adhere to the noble principles of typing. I respect a certain amount of that - there are legitimate cases for that type of stance - but it's not just about laziness. Adding a null check every time you reference |
Redeclaring document increased the time |
For those trying to cope with problems like this one, I came up with a band-aid: function given<T,R>(val: ?T, func: (T) => ?R, elseFunc?: () => ?R = () => null): ?R {
if(val != null) {
return func(val);
} else {
return elseFunc();
}
}
given(document.body, body => {
// your logic goes here, and body is no longer a maybe type
}) This will locally-dereference a maybe-value and only execute the callback if the value exists, casting it into a non-maybe type in the process, and returning the result of the callback (or null if the initial value doesn't exist). There's also an optional You can also chain multiple clauses like so: given(this.someObj, someObj =>
given(someObj.prop1, prop1 =>
given(document.body, body => {
// logic involving prop1 and body
}))) |
As the comment on a Stack Overflow answer says, you can use an This reduces the check to: invariant(document.body); Or: invariant(document.body !== null); You could view it as kind of a more verbose version of something like: document.body?.appendChild(el);
//^^^^^^^^^^^^
// (Not generally, but in this case where you're sure that
// `body` is non-null. It's about the type refinement.) |
I tried to look up "flow assert" and couldn't find any documentation... there's a third-party library called Either way, yikes. |
Any call of function with |
So it's simply any function with the name |
It's came from facebook internals I guess and was used by many react packages. There is also babel plugin to remove messages in production and only throw an error. |
Error ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ flow/js-stub-interface.js:5:11
Cannot extend Document [1] with DocumentWithBody because HTMLBodyElement [2] is incompatible with null [3] in property
body.
flow/js-stub-interface.js
1│ // @flow
2│
[1] 3│ class DocumentWithBody extends Document {
4│ // $FlowFixMe
[2] 5│ body: HTMLBodyElement;
6│ }
7│
8│ declare var document: DocumentWithBody;
9│
|
@monolithed try moving the |
@monolithed also keep in mind, as @OscarBarrett stated above,
|
This kind of null check on
document.body
should not be required:See question: https://stackoverflow.com/questions/42377663/flowtype-constantly-requiring-null-checks
If you dont want to implement this, please tell me how I can do it myself.
The text was updated successfully, but these errors were encountered: