Type Transformations Workshop (9 exercises)
explainer

How Excalidraw uses Mapped Types to Save Lines of Code

We are in the Excalidraw code base looking at types.ts.

Let’s look at the ImportedDataState type:

Loading explainer

Transcript

[0:00] We're inside the Excalidraw code base again. We're in a file called types, which is inside excalidraw/src/data/types. We have this type called ImportedDataState. This looks like when you import something from Excalidraw, it might be expecting some old config in there because we have this LegacyAppState in there.
[0:21] Now, we have an appState, which is on ImportedDataState, which is Readonly, Partial. Then we have AppState & a map type that does something, some sort of transformation, on LegacyAppState.

[0:33] What is it doing? Let's pull this out into its own type. We'll say, "type Example =" this. Now, that Example, we can see its isLibraryMenuOpen boolean, isLibraryMenuDocked boolean. It's taking the keys from this. We have T inkeyof LegacyAppState. This represents each key of LegacyAppState.

[0:53] Then what it does is it indexes into LegacyApp state with that key and grabs the first member of that tuple. If it were to grab the second member of that tuple, then we would see isLibraryMenuOpen. Whoops. Actually, that was supposed to be up there. We would see openSidebar and isSidebarDocked then.

[1:12] It's really interesting that they've chosen this type of way of representing it. It means that they have this code up here, LegacyAppSate, which they've probably maintained for a while. It means that they can just transform it into the state that they want it to be in down here, without actually needing to update it or add any more code.

[1:30] This means that PRs to remove this will just simply just remove it like that. Then the type down there will basically update automatically. This means you have a single responsibility for that type and that piece of state. Really cool.