Narigo
Narigo

Reputation: 3101

How can I secure my domain-driven types with TypeScript?

To make sure I don't use variables in the wrong context, I would like to statically check my code with domain-driven types. Is it possible to make the compiler warn me about the usage of a translated string as an identifier in the context below?

type Translated = string;
type Identifier = string;

function translate(key: Identifier): Translated {
  return `translated ${key}`;
}

const a: Identifier = "a.b.c";
const b: Translated = "hello";

const run = () => {
  const c = translate(b); // <- shouldn't this fail?
  console.log(c);
};

run();

Here is a TypeScript Playground Link for the code above.

Upvotes: 1

Views: 305

Answers (1)

JeromeBu
JeromeBu

Reputation: 1159

Here is a way to do what you are looking for (It comes from this article) :

interface Flavoring<FlavorT> {
  _type?: FlavorT;
}
export type Flavor<T, FlavorT> = T & Flavoring<FlavorT>;


type Translated = Flavor<string, 'Translated'>;
type Identifier = Flavor<string, 'Identifier'>;;

function translate(key: Identifier): Translated {
  return `translated ${key}`;
}

const a: Identifier = "a.b.c";
const b: Translated = "hello";

const run = () => {
  const c = translate(b); // <- Fails
  const d = translate(a); // <- OK
  console.log({c, d});
};

This flavoring can be use with numbers for Latitude, Longitude. Or for Ids : if you want UserId and PostId not to be possible to swap. Or anything you can think of... It is very convenient to avoid flipping types that would otherwise be the same.

Upvotes: 2

Related Questions