Become a TypeScript Wizard with my free beginners TypeScript Course: www.totaltypes... Follow Matt on Twitter / mattpocockuk Join the Discord: mattpocock.com...
Incredible insight, Matt! Declaring global types in TypeScript becomes incredibly practical, especially in scenarios like developing browser extensions, where you often use specific keywords like 'chrome' for Chromium-based browsers and 'browser' for Firefox. This is particularly handy when accessing features such as storage in extensions! Your explanation clears up a lot and makes it more understandable. Thanks for sharing this valuable knowledge!
I did this with electron for communication between backend and frontend: in electron the backend exposes functions to the frontend's window, and in order to have them typed I had to do: declare global { interface Window extends MyApi {} } This typescript feature that lets you merge interfaces like this is amazing.
my favorite use of the global scope is declaring JSX tags and Fragment from the interpreter I'm using, and then telling ESBuild to import React or whatever I'm using for jsx automatically so, no unnecessary obvious imports!
It's important to note that this is not for implementing something in the global scope but rather only for defining the structure of something that already exists in the global scope where the implementation is defined elsewhere.
A common use case I do this with Go/WASM which typically adds a function to global. I can add the declare global in the file that calls the WASM function and everything is typed!
This video was very good for understanding interfaces for me, i watched some videos about types vs interfaces, and only with this video example i was really able to understand interfaces and its benefits.
You also could create a types.d.ts and type Interface Window {bar: string} right? Im working with a js file and i have to type window with jsDoc and check with //@ts-check
I get this error on using declare global in my file - "Augmentations for the global scope can only be directly nested in external modules or ambient module declarations.": Error goes away if i export something from my file
This is not entirely on topic, but I don't know how to search for it. In Express I can say app.use('/:page", (req,res) => {console.log(req.params.page)}; and it knows that params has a page property in that function. How does that work? Thanks for all your insights ...
@@mattpocockuk Thanks. I did find paramsdictionary ... but haven't found the source of the parsing of /:id but better to continue the conversation elsewhere if you're interested.
What types are declared in global scope of TypeScript? Is, for example, Event/MouseEvent also declared there? I assumed it should, as this part of browser's API just like Window, but I couldn't actually found any of it in TypeScript repository.
Would it be difficult to have e.g., zod do runtime validation of the globals? I have used it for process.env and so far it's worked well for that but I haven't tried to integrate it with the DOM window or declare global yet.
I remember using it once for a 3rd party script that I had to use to call some external API but I gave up after some time since at some point it's become way too difficult to provide full typing. It turned out the API has also a legacy version I had to maintain, there was very little patterns between different calls, there were weird exceptions, etc. so I ended up rewriting the entire documentation of this API into my types. :D Instead I removed all the types and just pasted the documentation link in the comment. xD Job done, time saved, everyone knows how stuff works, and at the end of the day we usually anyway write some wrapper or facade for any such API so the full typing is not really necessary.
Thanks for this amazing tutorial. One question I have is when I type my Api responses or whatever types I have in my app, should I attach that globally or should import that type as Import type {MyType} from “..”?
_I _*_hate_*_ how those videos are so short_ as much as I love how they are straight to the point… *_No_*_ it’s not true I hate it even more for being so short…_ but it’s straight forward indeed 😅
I once used *global* to add my custom HTML element names to the HTMLElement name interface so I could get autocomplete when using *createElement*. Also, this is a great video; I love your insight into these topics.
This can be handy when extending global variable types like string, number, etc. You could therefore add methods to the StringConstructor or the string prototype globally
@@yourDecisi0n Wow, I get when people add something to global objects like window as sometimes there is no better way (e.g. Flutter does it), but modifying primitive types is another level of asking for troubles...
Maybe you can help with "CKEditor" component. It complains all the time "Cannot find the "CKEDITOR_VERSION" in the "window" scope." Some googling gave me a javascript solution that Typescript did not agree with. This video solved the type script issue but it did not stop the error. I added declare global { interface Window { CKEDITOR_VERSION: string; } } and in the component onInit() I added window.CKEDITOR_VERSION = '5'; //ckeditor5PackageVersion;window.CKEDITOR_VERSION = '5'; //ckeditor5PackageVersion; Can you tell what my mistake is? Thank you.
If JavaScript could fix it's hacky problems between CommonJS and ModernJS and add a 64-bit integer then TypeScript would be a lovely language. There are some places where you want to pull your hair out with JS. I like the way TypeScript does file level scoping.
Incredible insight, Matt! Declaring global types in TypeScript becomes incredibly practical, especially in scenarios like developing browser extensions, where you often use specific keywords like 'chrome' for Chromium-based browsers and 'browser' for Firefox.
This is particularly handy when accessing features such as storage in extensions! Your explanation clears up a lot and makes it more understandable. Thanks for sharing this valuable knowledge!
Global variables can be attackt with some special xss (if there is a vulnerability in your site). So you should avoid it.
There are types for browser and chrome
I did something like this in an Electron project where Node processes/functions are exposed to the UI via the global window object
I did this with electron for communication between backend and frontend: in electron the backend exposes functions to the frontend's window, and in order to have them typed I had to do:
declare global {
interface Window extends MyApi {}
}
This typescript feature that lets you merge interfaces like this is amazing.
my favorite use of the global scope is declaring JSX tags and Fragment from the interpreter I'm using, and then telling ESBuild to import React or whatever I'm using for jsx automatically
so, no unnecessary obvious imports!
It's important to note that this is not for implementing something in the global scope but rather only for defining the structure of something that already exists in the global scope where the implementation is defined elsewhere.
Matt is the absolute typescript goat
A common use case I do this with Go/WASM which typically adds a function to global. I can add the declare global in the file that calls the WASM function and everything is typed!
This can be handy for adding type constraints on global apis like localstorage
This video was very good for understanding interfaces for me, i watched some videos about types vs interfaces, and only with this video example i was really able to understand interfaces and its benefits.
I like to import definitions per file. So to use the global, I need to import a certain type def
How would you handle adding back the existing types to that new window declaration though?
You also could create a types.d.ts and type Interface Window {bar: string} right?
Im working with a js file and i have to type window with jsDoc and check with //@ts-check
I get this error on using declare global in my file - "Augmentations for the global scope can only be directly nested in external modules or ambient module declarations.":
Error goes away if i export something from my file
moduleDetection: force in tsconfig.json
This is not entirely on topic, but I don't know how to search for it. In Express I can say
app.use('/:page", (req,res) => {console.log(req.params.page)}; and it knows that params has a page property in that function. How does that work?
Thanks for all your insights ...
Google "augment express request object typescript"
@@mattpocockuk Thanks. I did find paramsdictionary ... but haven't found the source of the parsing of /:id but better to continue the conversation elsewhere if you're interested.
Thanks for you sharing!
😮 I tried doing this and I just ruined the types 😂 inn all project now i have a better understanding thanks 🙏
What types are declared in global scope of TypeScript? Is, for example, Event/MouseEvent also declared there? I assumed it should, as this part of browser's API just like Window, but I couldn't actually found any of it in TypeScript repository.
Would it be difficult to have e.g., zod do runtime validation of the globals? I have used it for process.env and so far it's worked well for that but I haven't tried to integrate it with the DOM window or declare global yet.
this is interesting, thank for those useful tips
Thank you so much.
Amazing. Now do globalThis.
this is common for a web3 developer
I remember using it once for a 3rd party script that I had to use to call some external API but I gave up after some time since at some point it's become way too difficult to provide full typing. It turned out the API has also a legacy version I had to maintain, there was very little patterns between different calls, there were weird exceptions, etc. so I ended up rewriting the entire documentation of this API into my types. :D Instead I removed all the types and just pasted the documentation link in the comment. xD Job done, time saved, everyone knows how stuff works, and at the end of the day we usually anyway write some wrapper or facade for any such API so the full typing is not really necessary.
You can't even imagine, how many time's I've trip over that problem...
Thanks for this amazing tutorial. One question I have is when I type my Api responses or whatever types I have in my app, should I attach that globally or should import that type as Import type {MyType} from “..”?
what about declare module as globals?
modifying an interface in a library, as in adding fields to Express.Request so it can be used across the app
_I _*_hate_*_ how those videos are so short_ as much as I love how they are straight to the point… *_No_*_ it’s not true I hate it even more for being so short…_ but it’s straight forward indeed 😅
What about a class? Should it be declared same way in global scope to be available as is in the script?
thanks for tips . Just in case , Can we use ( extend ) express-session like you said ?
I once used *global* to add my custom HTML element names to the HTMLElement name interface so I could get autocomplete when using *createElement*. Also, this is a great video; I love your insight into these topics.
This can be handy when extending global variable types like string, number, etc. You could therefore add methods to the StringConstructor or the string prototype globally
Please, don't ever make a public library with ideas like that.
@@DemanaJaire I just gave an example for a possible use case. Generally you want to avoid defining anything in global
@@yourDecisi0nthat sort of decision decision has hamstringed es6 adding flattening methods to Array because of some library pushing shit to Array
@@yourDecisi0n Wow, I get when people add something to global objects like window as sometimes there is no better way (e.g. Flutter does it), but modifying primitive types is another level of asking for troubles...
Maybe you can help with "CKEditor" component. It complains all the time "Cannot find the "CKEDITOR_VERSION" in the "window" scope."
Some googling gave me a javascript solution that Typescript did not agree with.
This video solved the type script issue but it did not stop the error.
I added
declare global {
interface Window {
CKEDITOR_VERSION: string;
}
}
and in the component onInit() I added
window.CKEDITOR_VERSION = '5'; //ckeditor5PackageVersion;window.CKEDITOR_VERSION = '5'; //ckeditor5PackageVersion;
Can you tell what my mistake is?
Thank you.
If JavaScript could fix it's hacky problems between CommonJS and ModernJS and add a 64-bit integer then TypeScript would be a lovely language. There are some places where you want to pull your hair out with JS. I like the way TypeScript does file level scoping.
+1. I'd also like the ability to define equality semantics on a per-type basis so that I can use an (x, y) tuple as a Map key, for instance.
Great video, I do this for adding types to some company internal libs that are written in pure js