· Jake Worth

Accepting string or number IDs in TypeScript


The robustness principle states: “Be conservative in what you do, be liberal in what you accept from others.” IDs from an API are a great opportunity to practice this principle.

IDs (AKA primary keys) from an API are typically numbers, so we might type our consuming frontend like this:

src/types/user.ts
export type User = {
id: number; // We expect a number
};

But, sometimes they arrive as string. Or, maybe we want them to be strings sometimes on the frontend, too. We can acknowledge this tricky situation with a TypeScript union of number and string:

src/types/primaryKey.ts
export type PrimaryKey = number | string; // Number or string

We can export and re-use this for any record-like thing:

src/types/user.ts
import type {PrimaryKey} from './PrimaryKey';
interface User {
id: PrimaryKey; // Numbers or strings are okay!
}

One tip: you might need to convert these at the boundaries. If you receive the ID as a string but need it sent as a number for database operations, you can convert it like this:

src/utils/converters.ts
import type {PrimaryKey} from './types/PrimaryKey';
export const numericId = (id: PrimaryKey) =>
typeof id === 'string' ? parseInt(id, 10) : id;

Here’s the usage demonstrated with tsx:

$ npx tsx
> const { numericId } = require("./src/utils/converters.ts")
> numericId(1)
1 // Stays a number
> numericId("1")
1 // Parsed as a number