Repository navigation
Assigning window.location after 5.8.2 upgrade fails #61335
Description
Activity
- addedNeeds InvestigationThis issue needs a team member to investigate its status.This issue needs a team member to investigate its status.
on Mar 3, 2025 MartinJohns commented
on Mar 4, 2025 ContributorMore actionsRelated: #48949
Reacted by KaiHad the same issue when upgrading to the new version.
A similar workaround to this one worked for me:
const win: typeof globalThis = window; win.location = window.location; // Pass
I see the PR #60987 added this part:
Document.location and Window.location now has stricter get/set types:
get location(): Locationis unchangedset location(href: string)previously allowed Location (probably because of Typescript's accessor assignability rules)
Seems to be the cause of the change, as
set locationexpects astring, butglobalThis['location']expects aLocationReacted by Matt CA pain for old style iframe prevention - ts-ignore helps
if (window.top !== window.self) { if (window.top) { // @ts-ignore window.top.location = window.self.location; } }How can anything satisfy the type
string & Location? Was it supposed to bestring | Locationinstead?Reacted by Chaz Gatian, Jacob Groß, Ben Hayward, Dylan Gattey, BreamIsAFish, Kai, Shelagh-Lewins, Dmitriy Pushkov, Dan Minshew, Phil Wolstenholme and 2 moreIndependent of whether or not this is a bug/regression: Shouldn't
window.location.href = otherWindow.location.hrefdo pretty much what you'd expect in most if not all of the cases?Reacted by Olivier Bellonephilwolstenholme commented
on Mar 31, 2025 More actionsThis is hitting us in our test files where we will often override
window.locationto mock it in order to test client-side JavaScript behaviour like this:window.location = { ...window.location, pathname: '/modals/main/change-to-delivery' };Reacted by Kai, Flinn Burgess, Marty Henderson, Dmitriy Pushkov, Bernhard Häussner, William Dibbern and Arno HilkeJake Bailey (@jakebailey) Ryan Cavanaugh (@RyanCavanaugh) sorry for tagging but this is a blocker for some codebases for upgrading to more recent TS versions, unless you add hundreds of ts-ignores. Is a fix planned, should someone make a PR or any other plans (it's been a month and no updates)?
https://developer.mozilla.org/en-US/docs/Web/API/Window/location says that reading the variable gives a
Locationobject, but that you can write a string to the variable.I can imagine that the type being
string & Locationis itself a problem (probably some known issue with getters/setters; you'll note that the DOM types do not actually have this type anywhere, so it must be created by the checker), it seems to me thatwindow.location = window.locationis not actually legal, no?Is this only working at runtime due to coercion to string since
Location.toString()gives a string? I can't see howwindow.location = { ...anything }should work, as that wouldn't even have atoString.The change came from: microsoft/TypeScript-DOM-lib-generator#1838
Is this only working at runtime due to coercion to string since
Location.toString()gives a string? I can't see howwindow.location = { ...anything }should work, as that wouldn't even have atoString.Yes, as far as I can tell from MDN and the spec. Writes to
window.locationare effectively forwarded towindow.location.href, which coerces to a string.saschanaz commented
on Apr 8, 2025 ContributorMore actionswindow.location = window.locationis effectivelywindow.location.href = window.location.toString(). Which works on browsers, but only with two magics under the hood:location.href: Thewindow.locationsetter is overriden so that the value goes towindow.location.hrefinstead.location.toString(): Given thatlocation.hrefexpects string, any passed value will be implicitly stringified.
The first magic is what's supported by microsoft/TypeScript-DOM-lib-generator#1838. For the second magic, I think in general implicit stringification is not supported, if you want to pass a string then you should explicitly do so.
And
window.location = window.locationis just weird, maybe dolocation.reload()instead? If you feel strongly about the current code, you can dowindow.location.href = window.location.hrefwhich includes no magic.Reacted by Ryan Cavanaugh and snarbles2saschanaz commented
on Apr 8, 2025 ContributorMore actionsBut the other part of me says maybe we should be less strict and allow passing
Locationwhere URLs are expected, as done in microsoft/TypeScript-DOM-lib-generator@2bffd44.Reacted by Jake BaileyI note that this code gives a TypeScript error, which doesn't seem like it can be intentional?
window.location = window.location;If you're here because you're stubbing some window location properties - you can bypass the assignment type check:
For example with a
jeststub:const oldWindowLocation = window.location; Object.defineProperty(window, 'location', { configurable: true, value: Object.defineProperties( {}, { ...Object.getOwnPropertyDescriptors(oldWindowLocation), assign: { configurable: true, value: jest.fn(), }, ), }); // do stuff... and then Object.defineProperty(window, 'location', { configurable: true, value: oldWindowLocation, });
Tom HT (@tomh-t) where should that be placed? Ben Ilegbodu (@benmvp) posted a similar fix a few years ago, but I can't either yours or his working. Typescript vis VS Code shows a missing property assignment near the end of the block. I tried at the top of the describe block, as well as inside the beforeEach block.
Andy Matthews (@commadelimited) - looks like a small syntax error you need to fix. I wouldn't trust a copy & paste in a github comment character for character - I have to edit it in here to avoid sharing irrelevant code and writing code in a comment is susceptible to syntax errors (missing curly)
But anyway - we're using this in a helper
export const withLocationMock = () => { const oldWindowLocation = window.location; beforeEach(() => { Object.defineProperty(window, 'location', { configurable: true, value: Object.defineProperties( {}, { ...Object.getOwnPropertyDescriptors(oldWindowLocation), assign: { configurable: true, value: jest.fn(), }, reload: { configurable: true, value: jest.fn(), }, host: { configurable: true, writable: true, value: 'initial-host-for-tests', }, protocol: { configurable: true, writable: true, value: 'http:', }, }, ), }); }); afterEach(() => { Object.defineProperty(window, 'location', { configurable: true, value: oldWindowLocation, }); }); };
And then in any test
describe('some test', () => { withLocationMock();
Reacted by Andy Matthews and Liam GardnerThanks my friend, I'll give that a shot...appreciated.

🔎 Search Terms
Unable to assign window.location typescript 5.8.2
error TS2322: Type 'Location' is not assignable to type 'string & Location'.
Type 'Location' is not assignable to type 'string'.
🕗 Version & Regression Information
⏯ Playground Link
https://www.typescriptlang.org/play/?ts=5.8.2#code/O4SwdgJg9sB0A2UDGBDALiKYAEBebokMCy6mYA3AFBA
💻 Code
🙁 Actual behavior
Failing with error:
🙂 Expected behavior
Expect it to either be a documented breaking change, OR it should continue to work as it did in 5.7.3:
https://www.typescriptlang.org/play/?ts=5.7.3#code/O4SwdgJg9sB0A2UDGBDALiKYAEBebokMCy6mYA3AFBA
Additional information about the issue
No response