Recent articles About

Compiling enterprise

Ivan Koshelev blog on software development

Pragmatic uses of Typescript type system 04 Domain Modeling with Typescript [2021 November 22] Typescript, types, domain modeling, literal types, tagged union types, template literal types

This article gives an overlook of Typescript features that let us provide safety guarantees for our code unlike any other mainstream language. Typescript is a somewhat paradoxical language. It is a superset of Javascript and Javascript has one of the simplest, least strict typing systems among mainstream languages, where even distinction between int and float or char and string are deemed excessive. Javascript is also dynamically typed, a trait that may seem down-right harmful to developers coming from Java or C# background. And yet, Typescript, sitting on top of JS type system, allows us to model types far more strictly than any other mainstream language.

Article is quite big, owning to almost 4 years of complex Domain Modeling experience in Typescript that I'm attempting to sum-up and considerable amount of ways in which Typescript language features can be applied to Domain Modeling. First part of this article explains Typescript features that we will use and is most useful to developers coming from other languages. If you are up to speed with TS, you can jump to the second part, which covers their application.

continue reading
Pragmatic uses of Typescript type system 03 Tag hierarchies via Template Literal Types [2021 May 09] Typescript, types, tagged union types, template literal types, hierarchy, polymorphism Features described in the articles require Typescript 4.3, which is in beta at the time of writing.

Tagged union types are a great part of Typescript, indispensible when working with groups of related data types, the kind we are likely to receive in JSON form from some API. They allow us to generalize groups of those types and strong-type functions that can operate on any member of the group.


const catTag = `cat` as const;
const dogTag = `dog` as const;

type CatRecord = {
    type: typeof catTag,
    name: string,
    huntsMice: boolean,
}

type DogRecord = {
    type: typeof dogTag,
    name: string,
    lovesFetch: boolean
}

type AnimalRecord = CatRecord | DogRecord;

declare const cat: CatRecord
let a: AnimalRecord = cat; // all good :-)
TS playground

This approach works fine in many situations, but its limits quickly become visible when we try modeling hierarchies of data.


const vanTag = `van` as const;
const ambulanceTag = `ambulance` as const;
type FuelType = 'gasoline' | 'diesel' | 'electric';

type VanRecord = {
    type: typeof vanTag,
    fuelType: FuelType
}

type AmbulanceRecord = Omit<VanRecord, 'type'> & {
    type: typeof ambulanceTag,
    medicalEquipment: string[]
}

type FuelStation = {
    availableFuels: FuelType[]
}

function canRefuel(station: FuelStation, van: VanRecord) {
    return station.availableFuels.some(x => x === van.fuelType);
}

declare const station: FuelStation;
declare const van: VanRecord;
declare const ambulance: AmbulanceRecord;

canRefuel(station, van); // fine
canRefuel(station, ambulance); // error!
TS playground

So how can we both have tagged types and make sure that 'canRefuel' function accepts any type derived from 'Van'?

continue reading
Flat DOM with adaptive CSS Maximum flexibility with minimum complexity in HTML components [2020 March 27] HTML, Dom, JavaScript, React, Components, flexibility, CSS-grid

Working on a suite of applications for a big enterprise, one understands the benefits of reusable components quite quickly. Chances are, at least 50% of functionality, like a user-friendly customer lookup, will be used in the majority of your applications with just a little bit variation in its functionality. Your users expect that this widget will be in a familiar place in every app, will look roughly the same and will act exacly the same. As an experienced DEV, you take a base component library and build your CustomerSelectorCmp on top of it up to the current requirements. It has all the necessary logic, it is used in 20 apps and it works great. Until new requirements come:

  • A new app is being commissioned, and CustomerSelectorCmp needs to have a horizontal mode for it; This will probably be used only in this 1 app;
  • Our managers have doubled sales numbers by grabbing tablets for client visits and having our app ready to go in the heat of the moment; But CustomerSelectorCmp could be much better with touch;
  • We have 10% of managers with special visual needs – it would be very nice to have accessibility mode for CustomerSelectorCmp;

5 years ago, trying to accommodate all this functionality in a single component would inevitably have to violate Single Responsibility Principle and lead to an unmaintainable monstrosity, where key CSS properties are overridden at-least 3 times each, classes are added just to increase CSS selector specificity and !important is your best and worst friend. Well, lucky we are in 2020! Thanks to CSS-Grid and React, we can have a base component that contains all the key functionality and can change appearance drastically with just a dozen lines of CSS and JS. See the following 3 dropdowns? They are the same component, rendering the same DOM! The difference is in 6-8 lines of CSS!

Grab the showcase project form github and lets dive in.

continue reading
Debugging JavaScript 02 Hints for debugging modern Web apps [2019 August 04] JavaScript, ES2015, ES2016, ES2017, ES2018, Typescript, Babel, Debug

This article will help you with debugging modern Web aps. ‘Modern’ here specifically means apps where source code undergoes a major transformation before execution, e.g. you are using Babel to enable features from ES2015-ES2018, TypeScript, and/or frameworks like Mobx that rely on transformations like decorators and transpile down to ES5. Because of the above, code that is actually executed by JS runtime is very different from what you see in your IDE.

You may be thinking, ‘but we’ve got source maps !’ While source maps are good, transforming ES2015-ES2018 features into ES5 changes code too dramatically, a single source line often becomes 3 or more during execution, this becomes _this, variable names change due to transpilation of let and const into var, etc. All of these changes really mess with debugging features like step over or examining variable values by their name. Debugging it can be a pain, but it does not have to.

Sample project for this article is avaliable on Github
continue reading
Advanced uses of Typescript type system 01 From mapped types to compile-time type construction [2019 July 21] Typescript, types, type mapping This article continues exploration of typescript type system applications. Previous articles on pragmatic uses of ad-hoc typing and mapped types showcased type system usages for application developers. This one will go a bit deeper, and is more useful for library developers. Make sure you fully understand concepts explained previously.

Generic classes in C# and Java can be thought of as class templates, which let us use placeholders instead of certain types. What they don't allow is having generic property names. Typescript does not have such limitation and easily lets us do that:

export type MakeProp<TKey extends string , TType> = {
  [key in TKey]: TType
}

// MakeProp<'foo', number>
type equivalent1 = {
    foo: number;
}
TS playground

This does not look so impressive, after all, we could have written this type by hand just as easily. What we should know, however, is that we have passed they type-key barrier ( not a real term :-) ) - we managed to make type into a key and create an object shape using only other types. This means, we can use our 'MakeProp' type within other generic types in Typescript. With mapped and conditional types, this means we can construct much more complex types with our mappings.

continue reading
< older
Ivan Koshelev photo

I'm passionate for anything that can be programed and automated to make life better for all of us.

Archives

  1. November 2021 (1)
  2. May 2021 (1)
  3. March 2020 (1)
  4. August 2019 (1)
  5. July 2019 (1)
  6. May 2019 (1)
  7. February 2019 (1)
  8. October 2017 (1)
  9. August 2017 (3)
  10. July 2017 (3)
  11. May 2017 (3)

Elsewhere

  1. GitHub@IKoshelev
  2. NuGet@IKoshelev
  3. LinkedIn