No Time Dad

A blog about web development written by a busy dad

TypeScript Type Assertion Example

I was working on imprving D3 forceSimulation example and ran into an issue that required me to use a TypeScript type assertion. Which is something I haven’t done much of before and required some research. Actually, the truth is that I first had to figure out that I needed a type assertion to do what I was trying to do. That in itself took a few hours of combing through examples on GitHub to realize.

The scenario I found myself in was that I had an interface with a property who’s value was sometimes a number and sometimes another type. This can be a problem for TypeScript because the compiler doesn’t know which type I’m intending to use. The solution was to use a TypeScript type assertion to tell the compiler which type I’m using. This is typically done using the as keyword or angle-bracket syntax.

interface Node {
  id: number
  x: number;
  y: number;
}

interface Link {
  source: Node | number
  target: Node | number
}

const link1: Link = { source: 1, target: 2 }

// Property 'id' does not exist on type 'number | Node'.
//   Property 'id' does not exist on type 'number'.ts(2339)
link1.source.x = 4

// TS compiler is happy because it knows the type is now
(link1.source as Node).x = 3

In the example shown above, D3 forceLink is expecting a unique identifier to connect a link’s source and target to two nodes. In this case, the unique identifier is a number that corresponds to the Node type’s id property. Later on in the code, the Link type’s source and target properties need to have x and y coordinates set. This is when I tell the TypeScript compiler that I’m using the type Node now instead of number.

In this specific case with D3 and the forceLink method, the identifier couldn’t be an object. It had to be a string or number as far as I can tell. Otherwise I wouldn’t need the TypeScript union and I could just set the source and target type’s to be of type Node.