You can do this with a generic query selector like so:
const frame = document.querySelector<HTMLIFrameElement>("#your-frame-id")
Typescript will then return a nullable type, which makes sense because it's not guaranteed this element will be found. You can get the contentWindow
window off the nullable object and then safely process it only if it's not null/undefined e.g.
const window = frame?.contentWindow
if(!!window){
//You can do stuff now with window
}
else{
throw new Error("Problem retrieving frame")
}
Notes
This is arguably slightly neater compared to Tiago's answer and Aayush's answer (as they are now at the time of writing). In particular, the type returned is nullable, forcing you to handle that case. However, it must be noted that since Typescript erases types at runtime, all three answers are no better at runtime than simply doing this:
const frame = document.querySelector("#your-frame-id")
See this codesandbox for proof. Sure, it has a compile time error highlighted - but it runs just fine. Here's the code:
import "./styles.css";
const app = document.getElementById("app");
if (!!app) {
app.innerHTML = `
<h1>Iframe Tester</h1>
<iframe id='x'></iframe>`;
}
const frame = document.querySelector("#x");
const window = frame?.contentWindow;
if (!!window) {
const child = document.createElement("p");
child.innerHTML = "Window found with origin: " + window.origin;
app?.appendChild(child);
} else {
console.log("Problem retrieving frame");
}
Importantly, this means if a non-iframe with the given ID is found, it'll be returned by the query; the query will not return null in this case. See this codesandbox for proof. Here's the code:
import "./styles.css";
const app = document.getElementById("app");
if (!!app) {
app.innerHTML = `
<h1>Iframe Tester</h1>
<p id='x' hidden>I'm not a frame, I'm a paragraph!</p>`;
}
const frame = document.querySelector<HTMLIFrameElement>("#x");
if (!!frame) {
const child = document.createElement("p");
child.innerHTML = "Frame found with inner HTML: " + frame.innerHTML;
app?.appendChild(child);
} else {
console.log("Problem retrieving frame");
}
Of course, in the main part of this answer, the access to the .contentWindow
will help rule out the case where there's a non-iframe element with the given ID- if this is undefined, then the else
branch will be taken. However, Shaun's answer may be safer as it dynamically checks the tagname and confirms at runtime that an iframe was found.
Note: the idea for my answer came from CertainPerformance's answer to a different SO Post. That post deals with the general problem of casting HTML elements in Typescript.