How do you emulate nominal typing in TypeScript?

You can use branded types:

type Index =  Number & { __type: 'Index'}
type CursorPosition =  Number & { __type: 'CursorPosition'}


function getElement(i: Index) {}
function getRange(p1: CursorPosition, p2: CursorPosition) {}

function indexFromNumber(n: number) :Index {
    return n as any;
}

function cursorPositionFromNumber(n: number): CursorPosition {
    return n as any;
}

const myIndex: Index = indexFromNumber(6);
const myPosition: CursorPosition = cursorPositionFromNumber(6);

getElement(1); // error
getRange(2, 3);  // error
getElement(myPosition);  // error
getRange(myIndex, myIndex); // error

getElement(myIndex); // ok 
getRange(myPosition, myPosition); //ok 

You need to define a helper function to create instances of the type or use type assertions ( const myIndex = 1 as any as Index), but the call site will give errors if you pass a simple number.

This article has a bit more of a discussion on the topic. Also the typescript compiler uses this approach for paths

Leave a Comment