Repository navigation
'window.location' should allow assigning a string #48949
Description
Bug Report
🔎 Search Terms
window.location, location.href
🕗 Version & Regression Information
- No version has the behaviour I'd expect, however up to version 4.5.5
windows.locationis of typeLocation, while from version 4.6.2 is of type(string | Location) & Location. FAQ do not mention anything about it.
⏯ Playground Link
Playground link with relevant code
💻 Code
window.location = "https://github.com/";🙁 Actual behavior
window.location = "https://github.com/";
// (property) location: (string | Location) & Location
// Type 'string' is not assignable to type '(string | Location) & Location'.(2322)While it's true that Location is an object and not a string, assigning a string to it is a long-established and recommended pattern, that may produce a different result from window.location.href = "https://github.com/";.
Example of where assigning a string to window.location is the correct behaviour: https://javascript.info/cross-window-communication#4q5rssu5ys
Also, according to MDN:
Though
Window.locationis a read-onlyLocationobject, you can also assign a DOMString to it. This means that you can work withlocationas if it were astringin most cases:location = 'http://www.example.com'is a synonym oflocation.href = 'http://www.example.com'.
Further discussion on difference between assigning to location or to location.href: https://stackoverflow.com/questions/2383401/javascript-setting-location-href-versus-location
🙂 Expected behavior
window.location = "https://github.com/";
// (property) location: string | Location
// No errorI could not find the rationale behind the change that happened between 4.5.5 and 4.6.2, that changed its type from Location to (string | Location) & Location, but I wonder if the intended result was the same I'm expecting here.
Activity
fcole90 commentedon May 4, 2022
I think this might be the relevant code:
TypeScript/lib/lib.dom.d.ts
Line 17194 in 9469f95
[-]Typing likely wrong for 'window.location'[/-][+]'window.location' should allow assigning a string[/+]MartinJohns commentedon May 4, 2022
The issue is that
windowis typedWindow & typeof globalThis(intentional), and that(typeof globalThis)['location']is typedLocation, notLocation | string. I'm not sure whereglobalThisis defined.As a workaround you can do:
andrewbranch commentedon May 4, 2022
globalThisis all the globals, and there’sdeclare var location: Locationelsewhere inlib.dom.d.ts. I guess this is intended to reflect the combination ofwindowcan be accessed as a globalwindowWindowiswindowIt’s a bummer because (2) has always been super weird to me and I wouldn’t have minded if TypeScript didn’t reflect that behavior, which would have meant the type of
windowwould just beWindow. As it is, I don’t know that we have any mechanism to make this work 😕fatcerberus commentedon May 4, 2022
Indeed it is, but that's just a side effect of the fact that
window === globalThis, similar to howglobal === globalThisin Node (globalThishaving been added specifically to standardize the name of the global object across environments). Just more legacy baggage we're stuck with from the earliest days of JS, liketypeof null === 'object'😞fcole90 commentedon May 6, 2022
Could we perhaps just fix this by changing the type of
globalThis.locationin the same way? Or am I missing anything?fcole90 commentedon May 6, 2022
Is it perhaps this the line where the
locationprovided byglobalThisis defined?TypeScript/lib/lib.dom.d.ts
Line 18253 in 9469f95
Or is it just one more place?
andrewbranch commentedon May 6, 2022
That’s the line, but the problem is that it’s a global variable, not a property. If it were declared as a property like it is on Window, you could change it to a get/set accessor pair with different types. But there’s no way to say that a
declare varhas a different write type from its read type.fcole90 commentedon May 6, 2022
Mmh, I see, so if we did
it would be wrong anyway as
locationcannot be of typestring🤔Are there other situations you're aware of where a global variable might need to be defined in different ways between get/set?
fatcerberus commentedon May 6, 2022
It’s technically not a wrong type even then, but you wouldn't be able to access properties of
Locationon it without a cast or a useless type guard, since TS would think it might be a string.andrewbranch commentedon May 6, 2022
I’m actually not sure whether this is possible outside of
window. My hot take is that maybe instead of declaring all these globals and then callingwindowWindow & typeof globalThis, there should have been a dedicated way to declare thatwindowis an alias ofglobalThis, and all its properties would be accessible without qualification, while global variables would still appear as properties on it like they do now. Then you could delete all thedeclare vars that are essentially duplicates ofWindowproperties. There could be some huge pitfall that I’m not thinking of since I’ve only been thinking about it for 30 seconds.fabio-colella-md commentedon Jun 8, 2022
Hi, any update on this? 😊
KKrisu commentedon Aug 3, 2022
(window as Window).location = 'abc'✔️el1s7 commentedon Sep 20, 2022
Typescript is full of annying shit like this, just do
aradalvand commentedon Jul 5, 2023
This should've honestly been fixed already.
adampl commentedon Jul 18, 2023
There's also the
window.location.assign(url)method that does exactly the same thing.Tanaykmr commentedon Jan 30, 2024
Is there any update on this?
Rinzwind commentedon Feb 27, 2024
Note that it is not equivalent in the case of differing origins. In the following example, buttons 1 and 2 change the location of the frame, but button 3 causes an exception (“Blocked a frame with origin "null" from accessing a cross-origin frame”). See the documentation on
Location.hrefandLocation.assign()in the MDN Web Docs.