-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
CheckJS cannot cast Element
to HtmlElement
types
#17453
Comments
/**
* @type {HTMLImageElement}
*/
const el = document.querySelector("#definitelyAnImage"); currently is equivalent to const el: HTMLImageElement = document.querySelector("#definitelyAnImage"); which will error, as the types are incompatible. However, in nightly we should now support const el = /* @type {HTMLImageElement} */ (document.querySelector("#definitelyAnImage")); (JSDoc casts attached to parenthesized expressions) const el = (document.querySelector("#definitelyAnImage") as HTMLImageElement); which is actually a cast and not an assignment, and I think matches up better with the answer this issue was looking for. |
Why would you expect to be able to do this without refinement checks? I'm more curious why |
@jcready Actually, it returns specifically null, and not undefiend. You'd probably need strict null checks on to notice in the type system, though. But anyway, it returns |
Ah, sorry about the |
@jcready Only if the |
Hi, OP here -- just to clarify, in the 1.14.x, the answer is that you can't fix this, but at some point in the future there will be an inline comment syntax to do type coercion? A thought just occurred to me, but I'm not at work so I don't have an easy way to test it. Would TS be smart enough to pass this?
It's extra verbose, and I happen to know that in my code the if-check would always pass, but it has the distinct advantage of being 100% vanilla JS without any TS-specific cruft. (The check could be any kind of runtime type checking, |
var x = document.querySelector("#foo");
if (x instanceof HTMLImageElement) {
x.src = "whatever";
} Is already interpreted and typechecked correctly today. |
This mostly works, but falls apart in closure scopes:
I can of course put another "if ... instanceof" inside the anonymous function but it starts to get a little ridiculous. The only good fix here is to provide a dynamic cast syntax as @weswigham stated (the one that works in Nightly). I started adding |
Does the JS checker not respect |
It does in certain ways, but to the compiler an |
I found another issue with this. ETA: this applies to any primitive types, not just String |
I'm just trying to avoid horribly verbose type checks, and at least in my environment I've found that let s1 = new String("foo");
let s2 = "foo";
s1 instanceof String; // true
typeof s1; // "object"
s1.constructor; // String
s2 instanceof String; // false
typeof s2; // "string"
s1.constructor; // String Note that |
IMO, it will be a long time to get the sort of co-dependent member checking that you need. Being practical, using custom type guards would be how I would solve this in TypeScript. I am not sure though how this would work in Salsa (and how much you are willing to restructure your code). In TypeScript you can pretty much contain any sort of "advanced" typing logic in a function, like you could do: function isString(value: any): value is string {
return value.constructor === String;
}
let s1 = new String("foo");
let s2 = "foo";
isString(s1); // true
isString(s2); // true |
I would not be averse to having a custom type-narrowing function, if that's possible in Salsa. Maybe I need to put in a new issue to support some kind of (comment-directive-based) type guard syntax for JS functions? I'm assuming that everything in #1007 is TS-only and doesn't have a JS equivalent? |
this should be working as intended now in latest. a few notes: This works because /**
* @type {HTMLImageElement}
*/
const el = document.querySelector("#definitelyAnImage");
el.src = "image.png"; you can alternatively cast in place using JSDoc const el = /** @type {HTMLImageElement} */( document.querySelector("#definitelyAnImage"));
el.src = "image.png"; |
This worked for me :) (document.querySelectorAll('.primary-menu > ul > li') as any as HTMLLIElement[]) |
@rohmanhm the original issue was about how to assert return types in vanilla JS (through |
TypeScript Version: 2.4.2
Code
For this JavaScript with
checkJs
enabled:Expected behavior:
Can cast result of
document.querySelector
which returns anElement
to anHTMLImageElement
Actual behavior:
Error:
The text was updated successfully, but these errors were encountered: