Strong Dynamic Type Checking for JavaScript
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Subtitle |
| |
Title of Series | ||
Number of Parts | 542 | |
Author | ||
License | CC Attribution 2.0 Belgium: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor. | |
Identifiers | 10.5446/61976 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
FOSDEM 2023129 / 542
2
5
10
14
15
16
22
24
27
29
31
36
43
48
56
63
74
78
83
87
89
95
96
99
104
106
107
117
119
121
122
125
126
128
130
132
134
135
136
141
143
146
148
152
155
157
159
161
165
166
168
170
173
176
180
181
185
191
194
196
197
198
199
206
207
209
210
211
212
216
219
220
227
228
229
231
232
233
236
250
252
256
258
260
263
264
267
271
273
275
276
278
282
286
292
293
298
299
300
302
312
316
321
322
324
339
341
342
343
344
351
352
354
355
356
357
359
369
370
372
373
376
378
379
380
382
383
387
390
394
395
401
405
406
410
411
413
415
416
421
426
430
437
438
440
441
443
444
445
446
448
449
450
451
458
464
468
472
475
476
479
481
493
494
498
499
502
509
513
516
517
520
522
524
525
531
534
535
537
538
541
00:00
Quantum chromodynamicsRule of inferenceWechselseitige InformationScripting languageJava appletVariable (mathematics)Open sourceComputer wormFluid staticsInterface (computing)TypprüfungCapability Maturity ModelSoftware developerLocal area networkGEDCOMCompilerWorld Wide Web ConsortiumTwin primeInferenceCodeCompilerElectronic mailing listBootingDefault (computer science)ParsingParallel portInformationMereologyMedical imagingParameter (computer programming)Library (computing)Compilation albumNatural numberSoftware developerCompilerWeightMultiplication signProcess (computing)Bookmark (World Wide Web)Web-DesignerPoint (geometry)Web applicationTypsichere SpracheComputer programmingResultantFluid staticsElement (mathematics)Axiom of choiceProjective planeIntegrated development environmentCodeRight angleVariable (mathematics)Quantum chromodynamics2 (number)Operator (mathematics)TypinferenzProgramming languageReference dataString (computer science)NumberFront and back endsBitInsertion lossKeyboard shortcutCartesian coordinate systemRule of inferencePotenz <Mathematik>CASE <Informatik>Computer filePredictabilityInternet service providerWeb 2.0Computer animation
07:32
Scripting languageWeb browserServer (computing)Dependent and independent variablesClient (computing)CompilerError messageVariable (mathematics)Run time (program lifecycle phase)Home pageRepository (publishing)CodeDynamical systemJava appletStandard ModelObject-oriented programmingCore dumpObject modelLibrary (computing)Element (mathematics)Revision controlPhase transitionOrder (biology)String (computer science)NumberProduct (business)Boolean algebraException handlingRun time (program lifecycle phase)Data loggerMultiplication signNumberConstructor (object-oriented programming)Category of beingCartesian coordinate systemTypsichere SpracheDifferent (Kate Ryan album)Product (business)Error messageConnectivity (graph theory)Quantum chromodynamicsReal numberStandard ModelLibrary (computing)Functional (mathematics)Object-oriented programmingException handlingDependent and independent variablesFile systemVideo gameCloud computingProjective planeMessage passingRevision controlProcess (computing)InformationOrder (biology)Software developerForm (programming)Validity (statistics)Open sourceKeyboard shortcutObject modelLogicCompilerService (economics)String (computer science)Cache (computing)Web 2.0CASE <Informatik>Web browserEmailServer (computing)DatabaseStandard deviationQuery languageSoftware bugRegular graphView (database)PrototypeLevel (video gaming)TypprüfungMereologyPattern languagePoint (geometry)Computer animation
14:57
Standard ModelObject (grammar)Complex (psychology)LogicError messageMessage passingProcess (computing)Continuous functionWeb browserGraphical user interfaceData managementProxy serverNatural numberRegulärer Ausdruck <Textverarbeitung>Parameter (computer programming)Run time (program lifecycle phase)Functional (mathematics)Generic programmingStandard ModelLibrary (computing)Object (grammar)Variable (mathematics)MereologyGame controllerValidity (statistics)Constructor (object-oriented programming)Different (Kate Ryan album)WordAttribute grammarCategory of beingObject modelError messageTypprüfungOperator (mathematics)Analytic continuationProcess (computing)Software developerCASE <Informatik>Covering spaceLogicMultiplication signSocial classStrategy gameComplex (psychology)String (computer science)NumberRevision controlCartesian coordinate systemFluid staticsDescriptive statisticsService (economics)IntegerCache (computing)Typsichere SpracheBitComputer animation
20:20
Message passingError messageProcess (computing)Continuous functionWeb browserGraphical user interfaceData managementQuantum chromodynamicsAddress spaceLocal ringData storage deviceInterface (computing)LogicCore dumpStandard ModelComputer networkObject modelRun time (program lifecycle phase)LogicLibrary (computing)Cartesian coordinate systemCore dumpMultiplication signMereologyElectric generatorProcess (computing)Projective planeSoftware developerCodeObject modelSpacetimeWeb browseroutputDifferent (Kate Ryan album)CASE <Informatik>Standard ModelProxy serverPresentation of a groupValidity (statistics)Sinc functionMathematicsData structureBitQuantum chromodynamicsData storage deviceInterface (computing)Vector potentialData conversionComputer animation
25:42
Multiplication signSoftwareRun time (program lifecycle phase)Validity (statistics)Standard ModelProxy serverFunctional (mathematics)Product (business)Mathematical optimizationSubsetDatabase transactionInterface (computing)Point (geometry)HookingInsertion lossFraction (mathematics)Declarative programmingGame controllerObject model
28:33
Program flowchart
Transcript: English(auto-generated)
00:14
All right, can you hear me in the back? Yeah, okay, perfect. So
00:21
Thank you for being here. I was not expecting such a large room of JavaScript developers and nothing has been broken yet So it's unbelievable So yeah, I'm here to talk about strong dynamic type checking for JavaScript Which may sound a bit weird because you are not expecting strong type checking and JavaScript in the same sentence, right?
00:41
But I will prove that we can do something about it So first, what is strong type checking? What do we mean by that? So let's do a bit of vocabulary So I try to find one definition online of what is strong type checking and couldn't find any It's like a never-ending argument about which one which language is strong and which one isn't
01:04
But I found two definitions commonly accepted The first one is that this strong type checking means that you have this kind of explicit binding Between some variable name and some type So this variable and this type are like bound together That means that every time you are calling variable by its name
01:22
You will get some reference data that matches the type you expect the second definition is More regarding the program language features like no lack of type safety due to loser typing rules For example for the case of JavaScript we have implicit type correction That means that it's perfectly fine to get the plus operator between a number and a string for JavaScript is just string concatenation and
01:47
Automatically casting the number to a string but for other languages like Python you will get a type error So that's taken as an example to show that Python is more strong stronger than JavaScript
02:01
So when it comes to JavaScript, whatever definition you pick you might say that JavaScript is not a strongly typed language and you will be right Because JavaScript is based on dynamic type checking, you got dynamic typing That means that JavaScript variables you can assign it to some type and then move to another type and go on
02:20
It doesn't matter So because types can change during program execution that makes types in JavaScript quite unpredictable So the creator of the language, Pandan H, justified his choice by saying that Developers can be more expressive when you got dynamic typing which means that can get to the result faster But he also agrees that it is also more error prone. So that's the image I took for this
02:47
Static versus dynamic typing. I think it's a pretty well So yeah, JavaScript and strong type checking not really actually every time you see someone complaining about JavaScript or mocking JavaScript It would be about one of these memes, right?
03:04
So these are some of my favorites maybe you know others But as you can see almost all these jokes about JavaScript are basically about the lack of strong type checking Which is too bad So some people will decide to just get rid of JavaScript and maybe go to a Kotlin or .NET or
03:23
Whatever language we have seen this morning But I think that's the most common solution to this approach has been TypeScript, right? I mean this thing has been invented specially to address this issue by having some optional static type checking About JavaScript. So how many of you are using TypeScript raise your hand? Wow
03:45
I was expecting that like almost 100% of these people in this room are using TypeScript I mean, why wouldn't we use TypeScript? It's so popular almost all the ecosystem of the libraries today on the NPM Ecosystem have been converted to TypeScript or provide TypeScript definition files
04:03
So we have seen this kind of exponential growth in popularity among the years. TypeScript is 10 years now It would be 11 in 5 days actually and it has never been so popular So did we solve the issue of type checking JavaScript with TypeScript? I would say not entirely and I explain why
04:23
Here are some things I learned about TypeScript after 10 years The first one is a bit of shock is that type checking is not actually the main selling point of TypeScript The main selling point of TypeScript is developer experience So if you have practiced TypeScript and the whole room has done that so it's great
04:42
You have seen some improvements in your development experience So many things like be able to export some API by using the auto complete Be able to detect some typos that you have done in your code be able to refactor your code more easily Thanks to the static type annotations
05:01
Maybe have some documentation right inside your IDE Some compilers are using static type annotations to bring some compile time optimizations, which is great You get type inference, great type inference in TypeScript So we don't have to write all the static type annotations at any time And we have seen some innovative use of TypeScript
05:21
For example, the Angular community is using a lot of TypeScript annotations to make some code generation, which is great So all of this is part of developer experience and it's great, but it's not really about type checking anymore It's much more than that I figured out that type checking was not the main selling point of TypeScript, or at least not anymore
05:42
When I looked at the esbuild project, one of the most important JavaScript projects of these last years esbuild, the famous bundler So maybe you are using the vite development server, some people in the room So vite is based on esbuild And does esbuild support TypeScript? Of course it does, everyone is using TypeScript
06:01
But the fact is that esbuild does not actually do any type checking when it compiles some TypeScript code All it does is look at the TypeScript code, look at the TypeScript part, the static type annotations, and just get rid of it That's all it does, nothing else And they say that running the whole TypeScript compiler is actually a loss of time today
06:21
Because of this development experience, developers have this whole integrated type safe environment and development process So that means that you don't need to do it twice a second time on compilation The second point of TypeScript that I learned about 10 years later
06:41
is that type safety in TypeScript can be easily defeated What I mean by that is that in many scenarios in your application, you are relying on type assertions That is, these little elements like the ASCII word, or the exclamation mark here Which is, I ensure the compiler that is not null
07:01
So all these things are not bringing any type safety, it's just the developer saying to the compiler Trust me, I know what I'm doing And most of the time, we do not So yeah, this problem, these type of sections, you can find them easily on any web application There are actually many parts where you are forced to use these kind of assertions
07:22
Because of the nature of the web You can have your perfectly type safe TypeScript application And still have to deal with lots of unpredictability Unpredictable is like, most of the time, your job for a front-end web developer And what I mean by unpredictable, it is known at runtime
07:41
That means it changes every time, at every user, and so on So for example, your application may have some backend services May call some APIs, maybe some third-party cloud providers And you are trusting the responses of these servers You are not validating any of the response of the server from the application side
08:03
So this could break You are also relying on a browser And some browsers have bugs and queries They do not fully support the JavaScript APIs, the web standard APIs I chose this logo for a reason, why? You may also have some client-side stored data for your application
08:23
Maybe you are storing on a local storage, some user preferences Or some file storage used as cache So this is likely to break as well Because sometimes the cache is outdated It comes from an older version of your application Or maybe it has been modified by the user itself, who knows?
08:42
And finally, maybe the most unpredictable part of every developer's job Did you guess it? The user The user can be very unpredictable If you have some application in production And have a look at the production database You will always find some crazy stuff like How did it get there? I don't understand
09:02
This is the user So yeah, all these things need to be validated Otherwise this is a recipe for disaster And can break your perfectly safe application in TypeScript So If you look at TypeScript and wonder How can I do that? How can I type check all of these things?
09:23
No luck, it's not a compiler problem Because all these things happen at runtime Right? You cannot anticipate it So it's more an applicative problem and not a compiler problem Which means that TypeScript is completely helpless And it is up to you, the developer, to find a solution to these problems
09:42
So how do we deal with runtime errors? Most of the time, the truth is that often we don't Maybe in the best of scenarios You are doing some custom logic to validate the data And trying to fix the stuff the best you can But most of the time you have so many different possible runtime errors
10:01
That you would have like try-catch blocks And trying to show some error messages to the user Saying them to call you and send us an email in case something bad happens And I also saw that we have some kind of global unexpected exception handler That is just sending all the runtime errors that you didn't catch
10:22
To maybe a monitoring service And it is added to a log file that you are checking like once in a month Looking at a bunch of errors and saying it's not worth my time So I should move to something else I don't know if some of you do that, but it happens, right? So it's too bad because we could figure a way to solve all these runtime errors
10:44
So back to this idea of strong dynamic type checking How can we do that? So I'm just sticking to the definition of a strong binding between variable name and a time here What if we could do this kind of strong binding but at runtime? What would it mean?
11:01
First it would mean that the type errors that we get would still be runtime errors Right? Because they are at runtime But at least they will be more explicit and more catch early That means that instead of having like undefined is not a function You will get an error message like this variable has been found undefined and it was not supposed to So instead of pointing to the consequences, it points to the source of the problem
11:24
So that helps a lot to reduce the investigation job that you have to do as a developer when doing debugging The second thing is that this strong binding should not be just a one-time validation pass I'm sure that there are plenty of JavaScript libraries that do that
11:40
That is, you are throwing a bunch of data to it and it validates saying true or false or just throwing a type error But we need more than that We actually need to have this binding that means the type information needs to live along with your data So it should be validated, this type checking thing, on every reassignment or mutation of this data
12:03
And finally the goal of this is to get rid of maybe some silent errors Because we have many mistakes in JavaScript that just are silent That is, you are not noticing them until it's too late And it can also make runtime errors maybe more predictable And so more manageable from a developer's point of view
12:24
So this is the main reasoning I have when I worked on the open source library That I want to present to you today, which is object model So definitely not a new project Actually, I've been working on this for the past eight years So I'm at the version of 4.4.1
12:43
That means that I have rewritten the entire thing like four times now It's obviously the hardest thing I had to code in my life I would say It's very complicated But it works So I'm glad And I would say also that it is my most used for real open source project
13:01
By used for real I mean that it is used in business projects So I use it in my professional projects Other people are using it as a fundamental component of their business project And I receive lots of positive feedback about this library You got an example here So what is this library doing?
13:22
So how do you use it? It's pretty simple actually The first thing you have to do is define the dynamic types I would say I would call them models I explain the difference later But basically it's that Let's say you are working on e-commerce application You can declare an object model for the order For example the customer order
13:41
Saying that you have a product which has a name property which is a string A quantity that is a number And also an order date After having declared this model You can now bind it to some data So this is where you have this strong binding between the type and the variable Here I used the constructor pattern
14:00
So that means you are calling new order I think it's probably the most intuitive form of a binding for the developer And also it helps to store the type information on the prototype level of the object So that's how I have this strong binding We already have a binding between object and prototypes in JavaScript And after having done that
14:20
You get the myorder object Which you can manipulate just like you would do with a regular JavaScript object But instead when you are assigning for example quantity to boolean instead of a number You will get a dynamic type error at runtime With an explicit message saying Expecting product quantity to be number and got boolean false instead
14:41
So because this happens Every time you are doing any mutation on an object It is really easy to quickly find some mistake that you are doing as a developer And so improve the debugging experience So that's great but how does it work? So let's start from a pretty basic example
15:02
Here I have a class user Having a constructor taking a name and an age And if you want to validate the parameters that are passed to a function And not rely on static type annotation in TypeScript That means that you will validate this data at runtime Maybe this data comes from an API for example
15:20
What you could do is use these if conditions And check the type of these different variables And throw type errors like that Pretty easy The problem with that is that it only works in the constructor So maybe you could decide to declare some setters Like set name, set age And had this validation process on every single attribute But it's a bit tedious and we can do better on that
15:44
So we can improve this by using a feature of JavaScript Which is the proxy So I don't know if everyone knows about proxies This is a feature of JavaScript that has been introduced in 2015 As part of ECMAScript 6 And proxies are actually really great feature
16:02
Really powerful The way proxy works is that they enable you to intercept Some operations that are done on some object And react to these operations So in this example I just use the set trap of the proxy Which means that every time I am reassigning a property I can execute some custom logic
16:21
So I can move my if type of name and different string and so on Into the set trap and be able to detect the different issues So that's great Now it works both for the constructor and the future reassignment The future mutations
16:41
What we can do as a first step Is try to make a generic function out of this Like so So now I just move the definition part On this generic type check function argument So the type check function take two arguments First is the data Second one is the definition or the type issue prefer
17:01
So it makes clear that you have this strong binding between objects and types And as you can see it is really easy to make a generic function to do this kind of stuff So the type check function that you see here Is a very basic version of what object model is Of course the library is much more complicated than that
17:20
It can cover many other use cases But you get the idea with this example So as you can see it is really easy to reuse this type check function To apply to it to many different models So why did I call these models and not types? Actually I wanted to find another word just to make a straight
17:42
That there is a few differences from the types that you know from TypeScript for example Because everything happens at runtime This is runtime data validations That means that models are more powerful than just the static types For example they can not only check the types but also the values Let's say I have a short model
18:01
Which can have a size which is either a number or a letter Like M, S, L, XL and so on I could decide to have this kind of type annotation To have both control that it is either a number or the letter M Or a string matching this regular expression I can also have some more complex assumptions
18:22
For example if I want integers in JavaScript Yeah integers in JavaScript So it will be still number in the end Because that's how JavaScript handles numbers It's a double 64 bits But I can add another assertion on this number model To say I need to check that it is an integer And maybe if I want it to be a positive integer
18:42
I can add another assertion to make sure that it's above zero So this is the kind of stuff of assertions that you can have And again every time you are manipulating this property For example the age of the user It will check all these assertions automatically And also the last difference from models to types
19:00
Is that model validation can affect application logic Because it's happening at runtime That means you need to react to it And have some strategies of how to handle these runtime errors For example if you got some error Some type error on your short model Maybe you just want to cancel the order So that you are actually making sure that Everything is happening correctly on your application
19:22
So these are the main differences So to get a look at the pros and cons of this library First the pros You get descriptive error messages They are pointing to the initial problem And not the consequences So just that saves you a lot of time
19:40
And it means that you now have this kind of continuous data validation As part of your development process That means you get faster debugging And more reliable applications in the end Regarding how you manage these runtime errors Because you need to do something right Not only showing an error message But maybe doing some strategies that are planned
20:02
You can define some global or maybe per feature Per model strategies about how to manage these errors Maybe some errors can be easily manageable For example clean up an outdated cache Or maybe some of them are more complex And then you need to maybe log them into a monitoring service
20:21
Some of the cons of this library One about performance of course Because since it's happening at runtime That means that it has a performance cost Don't worry it's not too much But if you are doing some heavy mutations Like more than 100 times per second Maybe you should avoid using dynamic time shaking For this specific scenario But most of the times you don't have to do this
20:42
So it's great The second problem is that it relies on proxies So you need support for it Today modern browsers are supporting ES6 proxies But if you have older browsers for some users This can be an issue
21:01
So which is better? Static time shaking or dynamic time shaking? The correct answer is you should use both Because they address different issues TypeScript we saw it It's awesome It improves a lot with the developer experience It makes you have a coding base which is reliable And makes sense which is logical But you should also take care of all the unpredictable parts
21:23
That are happening at the runtime of your application So my personal recommendation would be to Stick to TypeScript for the core application logic But also add this object model layer For every external interface that you have to deal with Like this server, the user inputs The local stores or the browser APIs
21:42
And this can lead to a more reliable application That's all I have for you today So thank you for listening And I'm taking questions Thank you very much So we have time for questions
22:02
Who would like to ask the first question? My question is Have you ever tried using this library with other libraries
22:24
For like as it's called Immutable data or YAP for other validation? So we actually don't hear you properly Have you tried using this library with other libraries For dynamic checking like YAP
22:41
Or for immutable data like IMR or other libraries? Yeah, so immutable should work fine For other validation libraries I mean it's kind of the same thing The same job So maybe it doesn't work that well And doesn't make really a sense But I think it should work Exactly with immutable data structures So IMR should work fine
23:12
Do you think it would be possible To generate the object model definitions I don't know what to call them
23:20
Object models from TypeScript Okay that's a good question So actually you can do the opposite That means that if you are using models It will generate TypeScript types for you But because this is more than TypeScript And as you saw this can affect application logic That means that we cannot do this simple conversion If you use it dynamic TypeScript Just like you would do with TypeScript types
23:42
You are just using like 10% of the potential of the library And it wouldn't make any sense to me So you should see the website Maybe to have more examples of that But yeah it's a little bit more than that Yeah I see hands You were there The next speaker also
24:00
Could you raise your hand or stand up Okay so we'll have to contact them A fantastic idea Love the library So you mentioned rewriting it four times over eight years How stable would you consider the project to be? How often do breaking changes to the API get introduced?
24:21
That kind of thing Yeah it's true that I rewritten it four times But the API never changed That's one thing And also I use it for professional projects So I would be embarrassed if I had to throw it away All right So it's quite stable for many years now
24:46
Hello thank you for the presentation And I would like to know whether Would you recommend using object model on projects that has not yet TypeScript Only JavaScript Thank you
25:01
Yeah I mean that could be a thing Although if you are into strong type checking You're probably already using TypeScript If it's not the case maybe it's fine I don't know But yeah it's totally possible But most of people are using TypeScript Thank you very much We have time still if you have time
25:21
For another question Yeah You'll have to be loud because people are moving And if you sit down please make sure there is no space Because the room is pretty full Hi thank you for your project So one other approach is using for example JSON schemas
25:44
That then translates to types Should I speak? One other approach is using JSON schemas For example on the validation side Let's say in a controller And the JSON schema then compiles to the
26:04
Or deduces the TypeScript type that the schema defined So that's one way for example to do validation And not have a runtime penalty besides doing the validation itself Have you considered this approach for your use case?
26:24
Yes good question So you can indeed use this kind of type declaration One problem is that Again if you are sticking to what can TypeScript do with static type checking You are only just using a fraction of what can be done
26:41
For example I told you about custom transactions I told you about the fact that you can check values Along with the types So all of these things would not match the model that you are describing with JSON So that means we need to have another API for that And that's why I have the own API for object model Another last question
27:02
And then please everybody squeeze no empty seat There are a lot of people still standing So JavaScript is executed with v8 And there is a lot of optimization underneath Where like you have a inlining going on Optimization of the function
27:20
When you use proxies all of that is going to be gone immediately Like the performance it is not only when you set something And when you would normally go through the proxy It's not a hook how's it called again forgot the name Anyhow like when you have the trigger for it
27:41
But also for anything that relies upon that data from that point on So it's going to be a huge performance I would definitely not recommend it and it's pretty much in production Yeah I talk about the performance issues One thing is that it's only useful for applying to external interfaces
28:01
Like network requests You can just validate everything related to one request So the loss of time due to the network request Compared to the loss of time due to proxy It's acceptable in my opinion You can debate after don't worry and he's gone I mean I run a bunch of transactions and it takes less than two milliseconds
28:23
So I don't think the loss of time is so much trouble Thank you very much Thanks again