No More any! We FINALLY Have Proper Types for JSON.parse & JSON.stringify in TypeScript

preview_player
Показать описание

Currently, when we are using JSON.stringify to create a JSON string from an object, we lose all the type information. This means that when you use functions like JSON.parse you are left with the „any“ type.

In this video we will fix that. We will create a properly typed JSON.stringify function declaration which will store the type information of the object the string was created from.

0:00 Intro
0:29 The issue
3:10 Fix it the easy way
8:10 Improve our Typings
14:45 Outro
Рекомендации по теме
Комментарии
Автор

Just to clarify for the people asking why this is useful. First: of course use zod or a validation library when you are unsure if you can trust the source. Also you are right that often we don‘t stringify and then parse again immediately.
But with stringify being able to keep the type information, we can use it as a „typed string“ everywhere and can make sure what kind of string we are dealing with. As I showed with the „writePersonObject“. We can make sure this function only takes a Stringified<{first: string, last:string}>.

Typed-Rocks
Автор

I think I prefer making parse return unknown and then validating in runtime to know how the object actually looks
what you shown here works if we have the type information available so if we either stringified a known object or annotate external source trusting it will always be a known string, but using the validation approach makes it more robust, fail proof, if for whatever reason you receive wrong string it won't randomly explode but simply fail the validation and behave gracefully

ZKIUS
Автор

what is the usecase for this ...I program for 20 years now and i never ever had to stringify and back to object. You only do one of those ...so only useful thing would be to have but then you can always cast it at the end

WicToR
Автор

Great video! Wouldn't `str.source` pass type-checking but then produce errors at runtime? I think using a unique Symbol key instead of a string key would prevent this.

filipbystricky
Автор

This is perfect for my use case. I am doing Server-Sent Events and wanted to keep the types between stringified version of the data being sent. Neither the object properties or the value change and I don't need a validation library for this since it is for internal use. Having those JSON.parse values typed will save me from looking for the file where the endpoint returns the data and manually checking what type of data is being sent.

daleryanaldover
Автор

8:14 If I understand it correctly, at this point we have a problem that parse pretends to return exact stringified class, while in reality it will be just an object with the same keys.
But improvements in the last part of the video seems to unintentionally cover this problem.

PurpleDaemon_
Автор

why did you build your own plugin for the inline code previews over using something like Quokka JS? Quokka's not free, but im curioius to know what problem you solved / what yours does better. Do i give yours a go?

benhaynes
Автор

Not sure if this falls into the category of so elegant it should be used always or so elegant it should never be used.

NuncNuncNuncNunc
Автор

The part about "how is this useful" was already pushed enough so...

My only minor "improvement" would be to use a "Symbol" instead of a normal string key ( in your example "source" ) here. Just in case the target object won't get this property in the future. This also guarantees you that your code set it, as its a unique key.

karamuto
Автор

you should probably just use structuredClone instead, which is also supported (i.e. doesn’t use `any`) by typescript out of the box

b_two
Автор

Typescript gymnastics. It's better to use a runtime validation library.

assertnotnull
Автор

R should be JsonifiedValue<R>, since toJSON can return an object!
However this is very cool for discovering the ts abilities, but I think it would be very impractical to have the Stringified type :/

MrEliteXXL
Автор

Surely the return type of parse should be JsonifiedValue, not JsonifiedObject? Since JSON.parse('5') => 5?

fauxparse
Автор

Awesome dude! Can you make a video about assertions? Would appreciate it!

MrJettann
Автор

This might be good practice but there is no use case for this. I almost never stringify and parse the same data in one code. I'm either sending it to the end user or parsing user input. And I have zod for that.

_PieceOfCode
Автор

As long as typescript still cannot generate javascript code for type validation, it will continue to be useless. It may be that expecting one thing or another is fine, but for e2e it is still useless.

stifskere
Автор

You never stringify something until you have to send it outside of your program where all types are useless

_PieceOfCode
Автор

Love your video. Any chance you'd consider making a PR to ts-reset for the typed JSON.parse? There's an open issue about it

gerkim
Автор

I consider this actually a really bad practice, like doing `JSON.parse(someString) as TheType`, because you could easily lose hours debugging a break-only-in-runtime project just to notice that someString wasn't matching TheType.
Better use some type of schema validator, like Zod, that checks the actual object at runtime, also giving to you the typing information, or, in case of unexpected results, gives you the error.
The only really useful thing here is the Stringified type, that will make your string variable carry some metadata from the source object. This could help someone not familiar with the project understand it quicker.

I know TS is very beautiful, but we need to take care to not make it also unsafe.

Diego-Garcia
Автор

Great watch! You should also release it as an npm package

abhishekmehandiratta