• Flattening Typescript Union Types

    In this post I describe how to flatten a union of two objects into one object - like joining two database tables. Click here to jump straight to the type alias for that

    Union Types

    Union Types in Typescript are a powerful way to describe a value that could be one of two or more types. They are useful in codebases that are transitioning from Javascript to Typescript, where one function may accept an input parameter that can be one of several different types.

    Here‘s an example of that in action, taken from the Typescript docs:

     * Takes a string and adds "padding" to the left.
     * If 'padding' is a string, then 'padding' is appended to the left side.
     * If 'padding' is a number, then that number of spaces is added to the left side.
    function padLeft(value: string, padding: string | number) {
        if (typeof padding === "number") {
            return Array(padding + 1).join(" ") + value;
        if (typeof padding === "string") {
            return padding + value;

    Coming to Typescript from a background of using Swift, I found myself rarely using union types. I preferred writing things that either used concrete types or generics. However, I recently discovered the typeof operator in Typescript and have been loving using it.


    The typeof operator allows you to create a type alias for the type of any typescript variable. When I first read about this operator I was thinking “Why would you want to do that?“. It wasn‘t until I was converting a large amount of Javascript code to Typescript that I saw the usefulness of it. Typescript is great at inferring the types of variables you’ve written. typeof allows you to pass around inferred types and in some cases that means that you can avoid writing types and interfaces yourself.

    Now, that’s a lot of abstract information, how does that look in practice?

    My favourite use of typeof has been in a codebase I work on where we build several ‘apps’ from one codebase. All these apps have different constants.ts files. typeof and import() have been incredibly valuable in automatically generating types for these files that can be passed around the codebase.

    // app-one/constants.ts
    export const COOKIE_KEYS = {
    	AUTH_TOKEN: ‘X-Auth-Token’
    export const CURRENCY = ‘USD’
    // app-two/constants.ts
    export const COOKIE_KEYS = {
    	LOGIN_TOKEN: ‘X-Login-Token’
    export const CURRENCY = ‘GBP’
    // shared/constants.ts
    type AppOneConstants = typeof import(“../app-one/constants”)
    type AppTwoConstants = typeof import(“../app-two/constants”)
    type AppConstants = AppOneConstants | AppTwoConstants
    // src/api/middleware/authenticationMiddleware.ts
    const authenticationMiddleware = (request: Request, constants: AppConstants) => {
    	request.addHeader(constants.COOKIE_KEYS.AUTH_TOKEN, ‘some-token’)

    Without typeof usages, we’d have to write and maintain an AppConstants interface that aligns to the constants files of each app. In addition to this, Typescript’s inference system can type things better than you as a developer can. For example, in the above code snippets, if you had written the type of AppConstants yourself, you might have said COOKIE_NAMES has a property of AUTH_TOKEN that is a string. However, the inferred type will tell you that AUTH_TOKEN is ’X-Auth-Token’ | ‘AUTHENTICATION_TOKEN’. This extra bit of context can be useful.

    Type inference has uses in other contexts. You could infer the type of an API response from a mock JSON file; or you could have varied Storage objects for a Web app versus a ReactNative app; any time that you’re having to write a lot of types with Typescript, it’s worth thinking if there’s a way you can have that type inferred for you.

    Merging Union Types

    Now, inferred types are great, but when you are saying something is the union of two inferred types, there will be cases where the two types don’t share properties. In this case, shared properties will be accessible on the union type, unless you add a type check to confirm which side of a union your instance comes from.

    Take the following data structures of a Superhero and Teacher for example:

    const spiderman = {
        pseudonym: 'Spiderman',
        height: 150,
        address: {
            id: 500,
            headquarters: 'Avengers HQ'
        photos: [{ id: 1, name: 'spidey.jpg' }, { id: 4, name: 'doc-oct.jpg' }, { id: 5, remoteUrl: 'https://www.spiderman.com/image1.jpeg' }]
    const mrTilbury = {
        firstName: "Arthur",
        secondName: "Tilbury",
        height: 180,
        subject: "Art",
        address: {
            id: 1231,
            streetAddress1: '1 Cadbury Lane',
            city: 'Norfolk',
            postcode: 'N1 KE5',
        degree: {
            university: 'Glasgow',
            subject: 'History of Art'
    type Teacher = typeof mrTilbury
    type Superhero = typeof spiderman
    type Person = Superhero | Teacher

    Now, as Teacher and Superhero both have a height property, I can access height on an instance of the union type:

    const getHeightDetails = (person: Person) => {
    	const heightInCm = person.height // OK, as both Superhero and Teacher have height
    	return heightInCm

    But what if we want to try and use the subject property on a teacher?

    const getSubject = (person: Person) => {
    	return person.subject // Compile error!

    Annoyingly, although Person is a union of a Superhero and a Teacher, we get a compiler error on trying to access person.subject because Superhero does not contain a subject property. (I would typescript ‘flattened’ these union types for you. Such that a Person had a property of subject that was string | undefined.)

    To handle this use case, Typescript offers a feature called “Discriminating Union Types”. This technique involves you adding a constant property to each side of a union that acts as a unique identifier for that type in the union. You can check if a property is ‘in’ the variable that is unique to one side of the union, e.g photos on Spider-Man. However, this value might change, or the Teacher type may later get photos and you’d have to update all usages of discriminating by photo to instead discriminate by another property.

    interface Superhero {
    	type: ‘PERSON’
    	...(other person values)
    interface Teacher {
    	type: ‘TEACHER’
    	subject: string
    	...(other teacher values)
    type Person = Teacher | Superhero
    const somePerson = {
    	type: ‘TEACHER’,
    	subject: ‘Maths’
    } as Person // Just using `as` for the example
    if (somePerson.type === ‘TEACHER’) {
    	console.log(somePerson.subject) // Valid! 

    By checking the type (our discriminator) is TEACHER, we can access all properties that are unique to a Teacher and not in Superhero. This is useful and allows us to access properties in one side of a union. However, it can be annoying to add a discriminating value to your objects (sometimes not possible), and it adds an unnecessary runtime cost.


    Now, the main point of this post. There is a way that we can generate a Person type that makes properties of both types in the union accessible, whilst maintaining type safety.

    // Converts a union of two types into an intersection 
    // i.e. A | B -> A & B
    type UnionToIntersection<U> = (U extends any
        ? (k: U) => void
        : never) extends ((k: infer I) => void)
        ? I
        : never;
    // Flattens two union types into a single type with optional values
    // i.e. FlattenUnion<{ a: number, c: number } | { b: string, c: number }> = { a?: number, b?: string, c: number }
    type FlattenUnion<T> = {
        [K in keyof UnionToIntersection<T>]: K extends keyof T ?
        T[K] extends any[] ? T[K]
        : T[K] extends object ? FlattenUnion<T[K]>
        : T[K]
        : UnionToIntersection<T>[K] | undefined
    type Person = FlattenUnion<Teacher | Superhero>

    (Note: this is using recursive types, a new feature of Typescript 3.7. Without recursive types, we‘d have to write a ‘finite’ version of this calling FlattenUnion -> FlattenUnion2 -> FlattenUnion3 for each nested object in a union)

    By doing this, we now have a type that allows us to safely access any property on either side of a union. Going way back to the example at the top, we can now access deeply nested properties without having to check if each nested object contains a value for a key.

    type Person = Teacher | Superhero
    type SafePerson = FlattenUnion<Person>
    // Using discriminating union, we have to check a property to verify the type
    const getPhotoWithId = (person: Person, id: number) => {
        if ('photos' in person) {
            return person.photos.find(p => p.id === id)
        return undefined
    // Using FlattenUnion
    const getPhotoWithId = (person: SafePerson, id: number) => person.photos?.find(p => p.id === id)

    (Note: this is using the new nested optional syntax in Typescript 3.7)

    By using the FlattenUnion version, we don‘t have to inspect the property to verify our photos property exist. We can autocomplete all properties - something that doesn‘t work with the discriminated union version as the keys on both sides of the union are suggested by Typescript.

    How is this FlattenUnion<T> working?

    To break it down, we take a type T and call K in keyof UnionToIntersection<T>. A simple keyof T would give us the set of keys that are in both sides of the union, whereas swapping the union for an intersection means that we get all keys, even if they are only in one side of the union.

    Now, for every key we say if that key is in keyof T (i.e. is this key in both sides of the union) then we want to use that value as is - it is not optional and we know it exists in both sides of the union. We want to say, take this value, and if it is an object, return the FlattenUnion of that object (the recursive part). However, before we can think about using FlattenUnion, we have one edge case to cover first - arrays in Javascript are objects. We say if the value is an array of any type, then leave it untouched. Else if the value is an object, recursively call FlattenUnion on the object, otherwise leave the value as it is (it is a number, string etc).

    If the key isn‘t in keyof T, then we know the value is in only one side of the union, leave the value as is but add an | undefined as we know that it is not in both sides of the union.

    You can play around with an example of this here

  • Potato Sourdough

    One of the many great foods that my mum makes is potato bread rolls. These are small rolls that we have alongside a meal, made from yeasted dough and either instant or normal mashed potato. They are light in texture and taste great.

    I was keen to try and bring this idea to the sourdough bread that I’ve been making as of recent. I researched online to see if there were any recipes available for this sort of dough, but I couldn’t see anything that exactly matched what I wanted - this was an open crumb and no visible pieces of potato. There were several recipes I found that were using real potatoes and mixing it in smoothly, however, the dough that they made was of low hydration, fast rise and a closed crumb. Similarly, I did find one recipe that matched those characteristics. But, it was one where you left in chunks of potato, which I wasn’t keen for.

    I eventually gave up searching and just thought I’d wing it with a recipe. It turned out far better than I could have hoped, so I thought I’d share it here. It makes for a brilliantly moist crumb and flavoursome crust.

    Potato Bread


    • 400g strong white flour
    • 100g whole wheat flour
    • 375g water
    • 11g salt
    • 110g levain
    • 250g potatoes, peeled and chopped into large chunks

    08:00 - Prepare Levain

    Prepare a levain in the morning by mixing 60 of flour, 60g of warm water and 60g of sourdough starter. (You may need to adjust ratios and timing based on the temperature of your kitchen or liveliness of your starter)

    17:00 - Mix Dough & Boil Potatoes

    Mix 350g water with the flour - we will save the other 25g of water for after the autolyse. Leave to rest for 30 minutes, covered. Whilst that rests, boil 250g of potatoes for 8 minutes. Once they are soft, remove from the heat and mash. Leave the mashed potatoes to cool until the autolyse is done.

    17:30 - Mix Final Ingredients

    Add the mashed potatoes, 11g of salt and 110g of levain to the dough and mix well. I like to use the ‘slap and fold’ technique. Cover and leave in a warm place.

    18:00 - First Fold

    Using a wet hand, stretch and fold the dough over itself at each corner.

    18:30 - Second Fold

    Repeat the previous set of folds.

    19:00 - Third Fold

    Repeat for the final set of folds then leave the dough to bulk rise.

    22:00 Pre-Shaping

    By now the dough should show visible bubbles and have risen noticeably. Turn it out onto a counter top and lightly flour one side of it. Using a scraper, starting at the floured side of the dough, pull the scraper round the dough and then back towards itself, creating a ball shape. Leave it to bench rest on the counter top.

    22:45 Shaping

    The dough will have spread out by now. Flour the top of it and then use a scraper to loosen it from the counter in place. Using the scraper, flip the dough so that the floured side now sits on the counter. Stitch the dough into a tight ball and place in a proofing basket. Either leave the dough to proof for 1-2 hours or put it in the fridge overnight.

    08:00 Baking

    If you proof the dough overnight in the fridge, the time at which you bake the next day is pretty flexible.

    Place a lidded pod into the oven and preheat to 240 degrees. After 45 minutes, remove the pot from the oven and the proofing loaf from the fridge. Turn the dough out into the pot and optionally score the dough with a sharp blade. Place it back into the oven for 25 minutes. After 25 minutes, remove the lid and continue to bake for another 15 minutes.

    Potato Bread

    Potato Bread

  • Muji Water Repellent Trainers

    Recently whilst on holiday in Milan I stopped in at a Muji store to buy some trainers I’d been looking at online. I‘ve now had them for around a month and I thought I’d lend my thoughts to any others browsing the internet for info on them.

    I went for a white pair of these shoes, though the black and the navy also looked great. It’s a subtle off-white that I think is far nicer than any ‘pure white’. If you have seen the 1970s Chuck Taylor’s that Converse put out recently, you’ll know what to expect.

    My only criticism of these shoes thus far is that they scuff really easily. At first I was trying to scrub off any marks from the front lip of the shoe. However, two weeks in I gave up and just let the dirt have its way.

    They say the shoes are water repellent but I don’t think you’ll ever see that in effect or see its benefits. This repellency does not apply to the small pieces of dirt that shoes pick up day to day, and it is this that you will notice.

    I’ve had no issues in particular with comfort, these feel as comfortable as any Converse that I’ve had in the past.

    Speaking of Converse though, these shoes are a bargain. They retail for £25 - the equivalent Chuck Taylors are £65 - and I can’t say I’ve any issues with their build quality. However, there is a question to be asked with how they can make shoes this cheap. It seems unlikely they can make these whilst being ethical and ecological but nonetheless, I don’t imagine Converse do any better.

    I’ve only had these shoes a short period of time, but I shall try and update this at some point to note how they’ve held up over time, and also just to add some more photos as Muji’s website photos are as minimal in numbers as their products are in style.

    Muji trainers

  • Slap and Fold

    Following my improvements of bread in my recent posts, I bought and read Trevor Jay Wilson’s Open Crumb Mastery. The key takeaway I got from reading it was that I don’t get nearly enough gluten development in my dough.

    The lack of gluten development in my dough means that when stretched, the dough will burst rather than bubble. This is what is limiting the size of air pockets in my dough - or the ‘openness of the crumb’. This weak gluten is also a key factor in causing my loaves to spread out once I start to bake them. A stronger dough will hold its shape and stand tall, whereas a weaker one will spread out quickly.

    I typically always used two things to develop the gluten in my dough. These were ‘time’ and sets of ‘stretch and folds’. I learnt this from “Tartine Bread”, “The Perfect Loaf” and “Flour Water Salt Yeast”. It’s a really popular way to make bread just now. However, I can’t seem to get the same results as others do with this method. I’m imagining it’s related either to the temperature of my kitchen, the quality of gluten in the flour I’m using, or the technique and frequency of my stretch and folds.

    My new approach for developing gluten uses what’s commonly called a “slap and fold” technique. It involves you putting a wet dough on your countertop, picking it up by two sides, slapping the bottom edge down on the counter and quickly folding the bit you are holding down over the top of the dough. You then turn your hands 90 degrees and pick up the dough from the right and repeat the same motion to fold it in the opposite direction.

    The results I’ve had with this have been brilliant. My dough feels stronger, shapes easier - with less flour - and holds its shape far better. It‘s even easier to score - giving me the most decorative loaves I’ve done yet.




  • Flour Cheat Sheet

    Flour Description Flavours Baking Properties
    Strong white flour (hard wheat) Made from hard common wheat, meaning higher protein that ‘plain’ flour. Typically this is around 11-12.5% protein in the UK. - -
    Very strong white flour Made from harder wheat, typically 13%+ in the UK. - A higher gluten content than softer wheats can result in tougher doughs.
    Emmer Ancient grain made from hard durum wheat, ~12% protein. Often used for pasta, sold as 00 (low extraction) flour. Earthy flavour, creamy in texture. Delicate gluten, but higher protein than common wheat.
    Einkorn Oldest ancient grain, softer member of the wheat family. ~11% protein. Grassy and nutty. Delicate gluten structure, sticky when hydrated and quick to ferment.
    Spelt Ancient grain, heirloom of wheat, ~14% protein. Easy to digest and nutritional, more vitamins than other flours. Milky, honey flavours Not great for high hydrations and long rising times (acid breaks down the gluten quickly)
    Kamut (Khorasan) A type of durum wheat, used by the Egyptians. ~15% protein. Buttery and sweet Very high in protein
    Semolina The flour of modern, common durum wheat, very common in pasta and pizza Buttery and sweet -
    Barley Barley is a grain that is high in fibre and low in protein - ~8%. Subtle earthy flavours, sweet when roasted Not great for bread on its own due to low protein, could be made into a porridge and added to a dough.
    Rye Rye is a blue/gray grain that has a vegetable gum in it that mimics gluten, it is very high in fibre and contains around 8% protein. Often used in scandinavian areas for dense breads. Tangy and grassy Slick, sticky and able to bind water.
    Buckwheat Buckwheat is neither a wheat nor grain, it is a pseudo-cereal, related to rhubarb and sorrel! It has high levels of starch and oil, protein of around 11% and no gluten. Nutty -
    Beremeal And ancient kind of barley that is grown in Orkney. Earthy, nutty -
  • Less Water

    At the start of this week I was feeling baking-confident and tried baking two loaves of bread at 80% hydration (800g of water to 1000g of flour, I typically go for 75%). It didn’t go well. The bread was hard to shape and I went out for the afternoon and left the dough bulk rising far longer than planned. Shaping the loaves proved to be difficult and when it came to baking, the dough had stuck awkwardly to the baskets - something I thought I’d learnt to avoid.

    To make up for this, on Thursday, I made two loaves at 60% hydration to see how well I could shape them. I was delighted with the results.

    60 percent water

    The bread cut easily and rose delightfully in the oven. I dusted them with rice flour prior to scoring in order to accentuate the scores.

    As much as I enjoyed its shape, I must say that I prefer the flavour of my higher hydration loaves. So, today I’ve got another 75% hydration dough rising, I’m keen to shape it just as well.

    As for the 60 percent well shapen loaf however, this morning I turned it into french toast using the recipe in Tartine Bread. It was incredible.

    Tartine french toast