Irakli Safareli

Type of Empty Record in Typescript


In TypeScript’s type system {} isn’t what you might think, it’s not a type for empty record:

let zz: {};
zz = {}; // COMPILES
zz = 1; // COMPILES
zz = "1"; // COMPILES
zz = true; // COMPILES
zz = { ff: true }; // COMPILES
zz = [11]; // COMPILES
zz = []; // COMPILES
zz = null; // ERROR: Type 'null' is not assignable to type '{}'.(2322) (when strictNullChecks is on)
zz = undefined; // ERROR: Type 'undefined' is not assignable to type '{}'.(2322) (when strictNullChecks is on)

So what to do if you want a type that will only accept empty record?

type RecordEmpty = Record<string, never>;

let kk: RecordEmpty;
kk = {}; // COMPILES
kk = 1; // ERROR: Type 'number' is not assignable to type 'Record<string, never>'.(2322)
kk = "1"; // ERROR: Type 'string' is not assignable to type 'Record<string, never>'.(2322)
kk = true; // ERROR: Type 'boolean' is not assignable to type 'Record<string, never>'.(2322)
kk = { ff: true }; // ERROR: Type 'boolean' is not assignable to type 'never'.(2322)
kk = [11]; // ERROR: Type 'number' is not assignable to type 'never'.(2322)
kk = []; // ERROR: Type 'never[]' is not assignable to type 'RecordEmpty'. Index signature is missing in type 'never[]'.(2322)
kk = null; // ERROR: Type 'null' is not assignable to type 'RecordEmpty'.(2322)
kk = undefined; // ERROR: Type 'undefined' is not assignable to type 'RecordEmpty'.(2322)

Another alternative alternative might be Record<never, never> but it’s not working as it should:

declare let r0: {};
declare let r1: Omit<{ a: never }, "a">;
declare let r2: Record<never, never>;
declare let r3: RecordEmpty;

if (typeof r0 === "number") {
  // r0: number
  r0;
}
if (typeof r1 === "number") {
  // r1: number
  r1;
}
if (typeof r2 === "number") {
  // r2: number
  r2;
}
if (typeof r3 === "number") {
  // r3: never
  r3;
}

r0 = 1; // COMPILES
r1 = 1; // COMPILES
r2 = 1; // COMPILES
r3 = 1; // ERROR: Type 'number' is not assignable to type 'Record<string,never>'.(2322)