DЕV.ВG Community Day 2025

Type-Level TypeScript | JavaScript / Илия Идакиев

47:40 · 21 Jun 2025 · YouTube

About this talk

This talk focuses on TypeScript, exploring its unique features and capabilities. The speaker, a fullstack developer with over 12 years of experience, emphasizes the importance of understanding TypeScript's type system, including generics and conditional types. He demonstrates how to use TypeScript for programming arithmetic operations at the type level, showcasing how one can create functions that perform calculations like addition and subtraction using types and arrays. Additionally, he touches on practical applications of TypeScript in building scalable applications and libraries, and the significance of adopting TypeScript's features for better code safety and maintainability. The session encourages developers to push the boundaries of TypeScript and explore advanced type manipulation.

Full transcript

Okay. Fore. [Music] So um I'm going to share a few words about me. Um I've been fullstack developer for more than 12 years now. Uh I am a Google developer expert in web technologies and angular even though lately I'm not so much uh writing Angular. I'm more into Nex.js. Um I've been a lecturer in Sophia University uh in the faculty of mathematics and informatics for more than

nine years now. And yeah, actually when I was putting these slides, I realized how how much time has passed since I started and uh how how everything changed uh especially now with with AI. It's just crazy when I go back 10 years ago and how different things are. Um I'm a big fan of uh of Typescript even though in the beginning because uh I was let's say

a hardcore JavaScript fan uh I I didn't enjoy it so much but I had to start writing it only because uh in Angular 2 uh it was integrated inside the library but anyways um I'm also very passionate about building scalable and performant applications and yeah I've been uh a lecturer uh pre-COVID I I used to do a lot of events uh lately I haven't done uh so

so many events because um yeah um I don't have so much free time to be honest. I I work a lot and I also have a small daughter and so on. So yeah uh the people with kids know what I'm talking about. Uh but yeah I'm very uh happy to be here on this uh awesome conference. Um and the funny part is that yeah not the funny

part but something interesting about me is that in my free time if I have like free time spare time uh I am a DJ I mean DJ is a strong word I used to DJ before I went to university uh when I went to university I had to stop uh because I couldn't deal uh learning and also doing this thing in the nightclub. So yeah I'm just

doing it from time to time if I have free time. And one interesting thing that I remembered when I was doing the presentation is that uh I had like a talk on dev be like my first talk on dev be in 2016 uh when I was talking about dependency injection in angular and yeah it just blew my mind that it was uh almost 10 years ago. So

yeah. Okay. So today uh I want to just set the expectations because I don't want uh to have disappointed people. Um, so today we're going to talk about TypeScript. Uh, but not the TypeScript that you're used to. Like it's TypeScript is a bit of a strange language because it's like a supererset over JavaScript and you are kind of writing JavaScript with this type annotations and so on.

Um, but yeah, today I'm mostly going to walk through a few things. Um, we're going to be dealing with types. And if you are a fan of functional programming, probably this lecture is going to be interesting for you because we are going to use certain concepts from from f functional programming. Um, and yeah, what are we what are we going to do? Uh, first we're going to

start by um seeing how using only the type system in Typescript, we can actually program. we're going to um create simple arithmetics so addition, subtraction and so on. And after that we're going to see a bit more complex topics. So I hope that is going to be interesting and useful for you. The main idea is to spark your interest if you're not already familiar with those concepts

and yeah some of the things that you're going to see probably if you're seeing them for the first time they're going to be a bit complex. uh but of course I'll share the presentation and also uh I have everything inside the stack blitz so I can also share a link to the codebase and you can test it out and play around with it. So let's jump back

to TypeScript. So as I said, Typescript it helps us a lot by being able to create different uh structures and like define the different types of our objects and so on and it's very useful when we want to uh be sure that our code is working correctly. It's like a real-time llinter type checker and it provides us code safety maintainability when we want to do certain refactorings

and also if new team members join it allows us to have uh uh completion in order to understand for example what are the function arguments and so on. So in general, TypeScript is great. Like it it improves performance a lot and I've been using it for I don't know remember it's a a long time probably since uh yeah since Angular 2 came out. So it's it's a

bunch of time. Uh so this is a like a simple TypeScript snippet that you might see somewhere. So we have some kind of an enum. We have a type that is called user. Uh we define the structure of the user. We have like a function called uh can edit content and we are checking to see if the user row is admin or editor and yeah based on

this you can either edit or not. That's pretty straightforward right and on the bottom uh we we create a user and we stick this type annotation that it's going to be of this type user and this restricts us from like playing around with different properties and changing the different types. So that's what Typescript is all about. The first thing that we're going to do is we're going

to focus on this part where we're creating actually the variable in JavaScript and then we're going to focus on this part where we're creating the function. So what I want to do first is kind of trans like maybe change your way of thinking when you're writing TypeScript because TypeScript is like for me it's very strange because you can write JavaScript in TypeScript and you can write TypeScript

it's a bit different with when it comes to types. So let's say that we want to create a variable I'll call it but it's actually a type in TypeScript. We can actually do this by just replacing the con with type in front and this produces a type that is called current user and it has these properties. Okay. But in general like if we are replacing the constant

and we want to be creating variables we also want to restrict those variables like we are restricting for example the variables in JavaScript when we are doing the type notation. So in we would like to do something like this right which it's not going to work because after all this is TypeScript so we cannot define the type of the type and this is where generics come. So

with generics we can actually create functions and these functions can provide structured output. So from runtime to type level when we want to create some kind of a user and yeah uh have it restricted to a certain shape of course we can use the generic this way. It's it's really interesting because now when we go back to the function can edit users we can also do the

same using generics. So if you want to if you want to say that for example our function is going to work on war argument we're going to define this argument let's say it's going to be called t and then we can use the extends keyword and say okay this variable let's say that we are going to accept is going to have this exact shape not exact but

we need to contain this row inside this um variable that we're going to get. So in general when we go to the type level the extends keyword we can think of it as the triple equals operator in JavaScript even though we're talking about types. So it's a little bit different of course but when we start thinking this way about the type system it's yeah it's kind of

it turns into a programming language. So the next thing that we can do is because we know the structure of the T that is going to have this row we can extract this row and we can check to see if this row extends admin or it extends user. So we can decide if we want to return true or false. And this is why I say the TypeScript

is very unique because yeah, we can write JavaScript with TypeScript on top but when we want to have fun we can just use the type system and write almost everything using types. So as I already mentioned generics on type level we can think of them as functions because you know they accept some kind of input and they produce some kind of output. So um the type level

constructs we saw how we can create variables. So variables in the type system we can use the type. We saw how we can create functions. We can create functions using the generics and we also saw how we can do flow control using conditional statements usually to turn a new operator. I think that there's uh no other way actually in the on the type level to do some

kind of uh decisions based on certain types. So now we come to the interesting part the iteration because iteration is a bit strange in when it comes to the type system. So the most common way of iterating over like let's say some kind of a type is using the key off operator. So what we are doing here is we're using a map type. This is how it's

called. So we're creating a generic and we say that this generic is going to be some kind of let's say an object and inside this object we want to define what the structure is going to be and we say I want to take every key of T and then I want to create the value of T. So at the moment we are not doing anything. So if

we receive an object we're pretty much outputting the same object but just by modifying something now we have something different. So now we say that if we take the variable user automatically we are putting read only to every property inside this variable. So uh we can also do conditional fil uh let's say filtering using the same methodology. So what we can do is of course again use

the mapped object but instead of just returning uh t of k so the the value we can check to see if this value actually extends string. So if is it a string and if it's a string we want to return it and if we don't want to return it we want to filter it we can use the never keyword. the neighbor keyword pretty much uh if we

have it it just ignored and this way we can create like we can filter out certain properties what I want you to notice here is that we here we are doing a something a bit different because instead of just returning the map object like the new object we are doing some kind of transformation so we are saying that we actually don't want to get the new object

that was filtered even though we can do that uh the only purpose why I'm not doing it is to show you that we can also do some kind of transformations here. So we are saying we want to get all the different types. So the let's say the values of our object and this when we have our variable user we actually get uh union of all the properties

that are strings. So this is how we can actually filter uh certain things. And the next thing that is very important how we can iterate and it's actually done automatically by TypeScript. This is uh using um union types. So whenever we have a union type, TypeScript automatically iterates over each element of this union and does something on it. In this specific case, what we're doing is we

are uppercasing each individual element of this union. Another interesting thing and something that u I like to ask on interviews because um I've been doing a lot of interviews for senior senior TypeScript developers uh is the infer keyword and the infer keyword is something that is very unique. We can use it in one specific case and this is within a conditional type. And what we are going

to do is let's imagine that we have some kind of promise. Usually the promise is some kind of container. This container holds a value. But again we're talking only about types here. So what we want to do is extract the the the the type of the value from a specific promise. How can we do that? So we can say that we're going to have a variable T

and then we're going to check is does this variable T extend a promise and if it does we want to use the infer keyword. The infer keyword what it does is that if the value that we provided is a promise it will take out from from the content the type and we can work we can do something with this specific type. So what we want to do

is just return it if it's true. If it's not then we'll just return the type that we got or we can just return never. So here we can decide what we actually want to do. And this way yeah if we have a promise that has a value if we use unwrap promise we'll just get the type inside the value. Of course we're going to get to more

uh interesting examples. But first I want to go through the basics. Hopefully you're understanding them because after a while it will we'll get a bit more complex examples. So here uh this is something that is already built in inside uh the TypeScript system. uh it's called parameters but yeah uh what it does is we can get the arguments of a specific function and again what we say

is we have the variable t if t extends a function we use the rest operator in order to gather all the arguments of this function and we use the infer keyword to assign those types into this arcs variable and then we say okay we return the arcs if it's not a function we just return never as I already and yeah this is the example oops uh how

it will look so we'll get an array of string and boolean and now we're getting to the interesting part why we are talking about infer because we are still not done with uh with iteration so uh another very common way in order to iterate inside the type system is using recursion. So let's think about um let's create a filter. So what we want to do is uh

filter out certain properties very similar to what we've done before that but we are going to work with an array of strings. So we're going to say we have a function called filter. This filter will accept one argument that is called t and this argument is going to be an array of strings. Then the second argument is going to be something that we would like to filter.

And what we can do is say okay if t extends an array then we want to infer. So we want to get the first element of the array. So we're going to say square brackets infer head. The head is like the head of the array. And again we can use the infer in order to get all the rest of the elements using the rest And I think

that now if you followed everything until now it's very easy. We are just going to say okay I want to check to see if the head extends this other variable that my function receives and if it does then we want to again call the filter function and then we're just going to eliminate we're going to remove this head because we want to filter it out and we're

going to provide the tail and also the value that we are filtering for. If it's not then we just create a new array with the head and also we call the filter with the spread operator. In all the other cases, we just leave uh not the other cases but the the rest of like the end case we just uh leave an empty array in order for everything

to get collected and yeah for everything to work and yeah uh we have rows different rows we are filtering for admin and we get all the rows that are not admin pretty there are certain limitation of course when it comes to this and probably you can figure out why their limitations because this is happening uh you know it's not like we're we're working with the TypeScript compiler

that is running inside inside our IDE and if we don't have certain limitations even though those limitations sometimes our IDs freeze because yeah it gets quite complex like uh calculating everything it's something strange um so let's see something a bit different, something fun and interesting in my opinion. So let's try because like in Typescript we already saw like creating variables and uh all the other stuff like

for example with flow control how we can filter things and so on. But let's talk about arithmetics because this is something that in Typescript it's not possible like in the type system it's not possible out of the box to do like calculations for example to maybe add two numbers and so on. How how do you do it? How do you do it in in the TypeScript on

type level? So to answer this like the the key here are arrays. So we're going to work with arrays. So we're going to define a function. It's very simple that just returns the length of an array. So we just say T extends array of any stuff and we just return the length of this T. That simple. Next thing, this is something that is very interesting and um

you need to understand it. Um how can we create an equals? For example, if we have two types like let's say the type which is the number one and the type that is number two. How can we check in about not compile time but in um in um in def time that two those two values are equal? Well uh we can say okay if t extends s

so if t is equal to s and if s is equal to t then we can return true otherwise we return false right. It's kind of correct. It looks really correct. The thing is that it doesn't work with union types because with union types we have this iteration that is happening and this is um yeah pretty much making this simple function not work. So we have to

do something in order to prevent this type distribution. We need to wrap those individual elements inside arrays. So, we're going to check if the array that contains one single element, which is T, extends the array with one single element S, and also the opposite. And this allows us to actually check if those two values are equal to each other. We're not going to be using this. I

just put it here because I think that it's interesting when it comes to uh arithmetics and also it's an important operation. So, yeah. So, next thing we're going to do a range. We want to create a function that we provide like let's say uh the number 10 and it produces this array from zero to 10. How can we do that? Of course, we're going to use recursion.

So we create a variable that's going to be a number and then we create another variable that has a default value. this variable like this is the way that we can actually create our own variables inside our functions when it comes to the TypeScript type level uh functions and yeah we just set a default value that is an empty array. So we're going to use this array

in order to collect some stuff inside and when we reach some kind of a end we're just going to return this array in some form and we're going to say okay so if the length of r equals the number that we provided the the end of our range of course we're just going to return the this collect this collection that we created otherwise we're going to do

a recursion. So we're going to call uh build range with the number and we're going to increase of course the the the array with one element pretty much and this element will be the size of the current R and that's pretty much it. So why are we doing this? Like I wanted to create this range in order to be able to to um create this limitation so

our ID doesn't freeze. So I'm going to create this type called allowed depth that will allow me to select only particular numbers and not force TypeScript the TypeScript compiler just to uh throw errors because um if we try for example to do certain like some of the operations that I'm going to show with big numbers everything will fail because of those those limits that we already saw

on the previous slide. this uh provides us this array that uh yeah we already understand but we don't need the array we actually need the union of all types. So we just use the number with square brackets in order to extract um all the different values that we can use. And now let's uh create why did I jump so fast to the next slide? I'm not sure.

Let me just go back. Um okay. So the next thing that we're going to do is create a function that we're going to provide a number and this number is going to be uh kind of we're going to create an array based of on those on this number. You're going to understand why we need an array. Just yeah be patient. So we say okay we're going to

get a number that should be from the allowed depth. And again I create this accumulator that is going to be an empty array. This is yeah pretty straightforward now. I hope that you understand it. And we say okay if the n extends the length of what we want to achieve then we just return it. Otherwise we call number of array and yep we spread the what we've

collected until now and we just add one additional element which is the type of unknown. It doesn't matter like what is the type that we're going to receive. What matters here in this uh array is the length. So we're going to be doing arithmetics using the length of our And the first thing that we're going to do is create the successor function. For example, if I provide

the number four to successor, we expect to get the number five. Right? This should be pretty easy. So what we're going to do is we're going to create an array of this number. We're going to create a new array and of course we're just going to add the unknown to this array and we're going to get the length of this array. Right? This is the successor function.

So now and of course we want to limit because otherwise we want we might get a number that it's bigger than the allowed ones. So we want to create this um um I forgot the the word sorry it's um intersection between the result of the length and the allowed depth. This will allow us to only receive a number that is from the allowed depth and not a

number that can overflow and break everything. And now what we can do is yeah use the successor. For example, if we call successor to 48, we'll receive 49. And if we call successor to 49, we'll just receive never because it's overflows the allowed depths. And now we can create addition. It's really easy with addition. We just need to merge two arrays. And probably we just need to

get the length of those arrays. And now we can add two numbers. Of course, we limit the result again to the allowed depths. And now we can add numbers. We can add three and two. And we will say five. Now we can do subtraction. So I'm I'm just going to go a bit faster through those because I don't have so much time left. Of course you can

check them out later. The slides are going to be available. Uh and you can check if they're correct or not. But they are because I already checked them. And here's the subtraction. Again what we are doing is we are in this is an interesting thing because like we are um we are getting like we're constructing an array of a certain number and then we are saying okay

if it extends another array and then we use the spread operator over the um number to array of the other value and we infer the rest of the element. So we're really what we're really doing is subtracting arrays. That's the interesting part. So it really works. Of course, we can do multiplication. It's a bit complex, so I won't go through it. And we can also do stuff

like creating is less than or equals to check to see if like certain um type is equal or less to another. and also is less than which we just invert those those values. Again, I'm saying this not so much to I I understand that you won't understand absolutely everything that I'm showing. The mo the main idea is to spark your interest and to sit down and maybe

write a few of those functions and I'm also at the end going to share some materials uh that you can watch. And yeah, I'm I promise you it's going to be fun. And this is uh yeah pretty much uh the end. So we have also division and uh mod modulus I think it was called um and yeah we pretty much created simple arithmetics using TypeScript. It's mind-blowing

in my opinion. Uh but yeah so it turns out that if we have no limitations over the recursion and also no limitations over the union TypeScript type system is incomplete and it's true actually not sure how many of you know that but a guy sat down and spent a lot of time he removed all of the limitations of the TypeScript compiler and created Doom Um, and this

was three months ago. I felt like it's one year ago, but yeah, it's uh it's crazy. And you can check it out like it's in GitHub and you can also watch uh uh his videos actually the Michigan TypeScript uh YouTube channel if you if you are interested in such things. I've left a link uh at the end. You can check it out. They have some really interesting

um videos where they solve different tasks. um they're more fun than than the ones that we saw. So So how does this help us being like developers? Because obviously yeah I mean it's fun creating arithmetics. It's fun maybe creating Doom in TypeScript even though I'm not sure uh who has so much time to sit down and do it but obviously there are people um well it it

really doesn't. I mean it's fun and people do it just for the sake of it. But what it shows us is that actually TypeScript is super powerful and just by learning these concepts that we went through like some of them maybe I've missed something uh and there's a few other things that um I can show and I will show um we can yeah we can create some

really powerful libraries and tools and yeah usually like because when I worked on a lot of projects and very often you need to create some kind of utility functions or helper functions or some kind of transformers and so on. And people that are kind of scared or they're not so much they're not so familiar with the TypeScript type system often they just use a lot of Annies

and yeah we are not type safe let's say and I ask you don't be don't be afraid just try it out there should be a balance between what you should um let's say type and what you you should not because I often fall into this case where I try to type some kind of a utility function and I want everything to be typed and I lose a

whole day of just working with types instead of focusing on uh creating the functionality and this is a problem because the the customers and the users of your applications they don't care about the types you know types are for us the developers so yeah you just you just need to find the the limit and when you see that something is not working out maybe figure out how

you can break it into smaller pieces or change it a little bit in order to um maybe type it but what um yeah why why am I in general talking about type level TypeScript um yeah five I think it's five yeah five years ago I created this library um it's not of course as you see very widely used but uh I used it in probably all of

the Angular projects that I've worked on uh because uh um I was using ngrx. Um, are there any angular like people here? One, two. Okay, there are a few. So, with ngx, it's like a it's very simple. It's like a redux pattern. Uh, and yeah, you have the store, you also have but you also use ajs and as a really big fan of functional programming. Of course,

I'm a a big fan of EricJS and I'm really sad that lately I cannot use it so much because um yeah, I'm mostly working on next projects. yeah, I created this library that's should be really a utility function that allows me to create this kind of bun. I call them bundles. So yeah, we're today I'm just going to go through a couple of slides and we're going

to create something sim similar. Uh and my idea here is to actually show you that the things that we learned until now are useful and yeah I mean you can just utilize them in your day work. So the idea of um these bundles is yeah to let's I I'll just wait a little bit uh to explain. So let's start uh let's start fresh. So when we when

it comes to Redux, what we have is we're dispatching actions, right? And usually we have this this this action creator. So if you use TJX, you're going to find something very similar to what I'm showing you here. Uh we have like a factory function that allows us to create events and using the props, we can just define uh what type of payload we're going to have in

this action. uh and then yeah pretty much we can see that we have type deposization for the type of the action and also whenever we call the function we have typeization for uh the payload. So let's see how we can create this uh this thing and later uh we are going to see how we can extend this example by creating those bundles that are for going to

be for asynchronous actions. So creating the event is pretty easy but we use this props uh function. This is only a utility function. I didn't invent it. I pretty much got this logic from uh NGX itself. I like to read the source code uh from time to time of libraries in order to see how uh they created things. And it only exists to support us uh the

developers to have like a better API because I'm not sure how many of you try to create a library but it's extremely hard to create uh a nice uh API a nice way of using your library and also for it to be maintainable. So often um people who write libraries they create these utility functions in order to make things a bit more clean let's say and what

it does it just receives uh one argument t and it just returns it pretty much and we use it as so. So the interesting part is creating the event. So the event is going to accept one argument that is going to be a string and the other argument that is going to R which is the props function the result of the props function and pretty much this

is it. So inside the inside the function we're going to create like the so-cal creator and we're going to define that this creator is going to get a payload. We check if this R argument that we received from the props function is void. Meaning that it's provided or not. So if we have not provided the props function to the create event, it's going to be automatically void

because we we signed it on line seven at the end. We put a default value for it to be void. And if it's void, we just want to um return void for payload. So our action does not accept any payload. If it's not void, then we just return the type. And again, for what we're going to return from this creator, we check okay is our void. And

if it's void, we only return the type, which is the string that we provided for our action. If it's not void, then we create a payload inside this action and we implement the logic. As you see like on what is it line I put s any and often you'll see me adding this s anyies inside the bodies of the functions because usually with utility functions you should

not spend so much time into um defining of course it depends on the complexity but if it's a simple one you should not so spend so much time into defining the depation inside the function because I just don't want to waste time the important thing for for me is this function when people use it to be typed uh not um yeah to be typed so we can

understand what actually it's returning and yeah pretty much that's that's it we have the create event function. So now let's create our asynchronous bundle factory. So when it comes to asynchronous events we have a few things uh that happen. So we have the trigger. So we we trigger the action and we have certain outcomes right? So whenever we are working with let's say HTTP codes we trigger

the load let's say users and we have a few other actions that we also need we need the success for this action we also need the failure for this action and because it's an asynchronous operation sometimes we just want to cancel it so we want to create a cancel action and the whole idea of this library that I created is exactly this so whenever I want to

create actions instead of creating one single event and having this boiler plate uh copy and pasting, copying and pasting like most of the people do. I just uh or at least they used to do it. Um I just use these bundles and I generate actions for everything that I want. And pretty much the code will look like this. And then we're going to get these bundles and

we're going to provide to another function that automatically will connect everything to let's say the Redux store. And instead of me doing some extra work, I'm just going to use this um object in the site is called ASIC bundles. And I'm going to do all the control from here. So I can dispatch events. I'll be able to listen for events. I'll be able to create events. So

let's create some helpers. We're going to create a helper called ASIC bundle. We're going to get the type the string of the action and of course we're going to get the different props for the different uh cases. Right here we're going to use template literos inside the map type key and we're going to say okay I'm going to get the key that is inside um so for

each no actually here we're creating a new type uh and we're just getting the string u that is provided for the given action and we're just creating a new how should I say new property on this type object And what we're doing is we're capitalizing the first letter. So for example, if I created let's say if I use create action with load users here I'm just going

to get a property called trigger load users and it's going to be camel case. So by using type literal inside the map types you can change uh the variable names and you can also put static parts as well. And what we'll do is just it will return the return type of the create event. We do the same with the success. So for example here the type of

my action will be load users success came. We do the same for the failure. So it will be load users failure and of course cancel load users. And as you see we use uh the uh amperand it was called in order to connect everything into one type. And this way we create the new object that contains all of those Now we can get to the implementation in

JavaScript. It's not very um crazy like in in JavaScript it's easy. And yeah we have this thing called create bundle. let's jump because we don't have so much time into creating this other function. So the other function will get an array of those async bundles and it's going to create all those different um communication methods that I can use for all of the bundles that I provided.

Okay. And yeah, as I said, we're going to have dispatchers. So using the dispatch property, we're going to be able to dispatch all the different events directly to the to the store or wherever they're going. uh with listen we are going to be able to listen for all the different events like in Ericjs as I mentioned we're using observables so we can like subscribe to different events

from here as well and also we can use the action creators in order to create actions if they're needed okay so I'm just defining the observable type here uh because yeah uh I have it in the example that I'll share later because I have not imported arjs or anything but yeah we are going to just define it for simplicity and we're going to create this very important

type that is called union to intersection. So the idea is if we have a union type to create the intersection of the union. So we say something very interesting here. We we we define the argument u and we say that the argument u is going to extend any. This is always going to be true. Right? This is this is why typescript type system is a bit crazy.

So we can do something like this. U extends any in this case I'm just going to create a new function and this U argument is going to be actually the arguments of this new function and then I say otherwise yeah otherwise uh it will never happen and then I'm going to try and get the the result of this and I'm going to say okay if this extends

a function and I know that it extends a function because I created this function I want to infer a new value which is I and if this is true I want to return I otherwise I'll just return never and what this does is that yeah we have a union and it creates an intersection out of the types and this is only because this is how Typescript works

pretty much it just works out of the box and this is something that you also have to remember and keep it in mind when you're working with the type system that yeah I mean it just this is how Typescript works in order to be able to kind of um because you're putting certain restrictions in order for those restrictions to be um complete. Yeah, let's say uh TypeScript

just distributes them not distributes them but just creates uh this intersection type. Okay, now a few easy helpers. Element of that allows us to uh to provide an array and get the union of the elements. We're going to use this for iteration. And now we're going to define the listeners. So these listeners are the observables that we can listen to. And we say again we have this

T. We're going to iterate over the keys of this T. And for each key, we're just going to put this dollar sign on the back, which is a convention when we're using observables in order to mark that this property is an observable. And then we just say observable. And if this is a function, yeah, we just um yeah, we just return the type like the creator of

the function pretty much. Otherwise, we check to see if uh yeah, otherwise if it's not, we just return this empty Um I'm just going to quickly go through the other ones because I don't have so much time. But yeah, this voidify uh it's really interesting. I just am iterating over each function and I'm if it returns something I'm just saying that it will return void from now

on because like for the create for the dispatchers I don't need to create to return anything and yeah create asynchronous bundles. we get the array pretty much uh and yep we say that we're going to return a new type with create dispatch and listen and we're going to use this um union iteration. So we're going to uh get all the elements of this uh list that we

created and we're just going to transform them with the specific functions that we just defined and we don't even need to care about the implementation because we are dealing every we're creating everything on type level and yeah pretty much that's all. So what we created is we have this create actions that have depation which is great. We also have the dispatchers as you see it's returning void

but also it accepts the proper payload. And we also have the subscribe and inside the subscribe what we can do is also have types for um yeah the things that we're going to be working with. And that's pretty much it. I've spent so much time into creating this library five years ago and it's funny how I can just fit it in a few slides and present it

to you. Of course, it's a bit more complex when it comes to Angular because there are certain concepts that you have to implement there as well. But in general, if you have those um um as a base like the those types that I showed you as a base, it will be super easy for you to actually create it. So, I've um I've shared a few links. So,

first is the YouTube uh channel uh Michigan TypeScript that you have to definitely check if you're interested in more in the TypeScript type system. And I also added a few other uh links for education. The rest of the links on the bottom uh if you're using um if you don't want to create certain utility types like the ones that I created, you can use TSD or TS

essentials or TS tool belt. There are uh all kinds of different libraries that provide you with such types out of the box. So you can also use them to learn. You can you can go through GitHub and yeah, examine the source code and see how they're doing those interesting types. And yeah, thanks very much for your attention. Uh and hopefully this was uh interesting for you. Again,

the idea is more to spark your interest and not so much for you to understand every single bit that I uh presented. Uh and if you yeah want you can yeah send me a message if you don't understand something like uh maybe later on LinkedIn or whatever but yeah I'll be happy to u check the questions if we have time we have time or not exactly because

I see that It is neighbor.