object

Matches any non-primitive value — objects, arrays and functions, but never a string or number.

Signature
declare function create(o: object | null): void;
  • Added in TypeScript 2.2

Errors

Passing a primitive where object is expected is a compile error: "Argument of type 'number' is not assignable to parameter of type 'object'."

Changelog

  • PHP 2.2object introduced to represent the non-primitive type — anything that is not number, string, boolean, symbol, null or undefined.
  • PHP 3.2bigint added to the list of primitives excluded by object.
  • PHP 2.0Under strictNullChecks, null is no longer assignable to object; write object | null as the docs' create() example does.

object is the non-primitive type: everything that is not number, string, boolean, symbol, bigint, null or undefined. Object literals, arrays, functions, class instances, Map, Date — all assignable. Primitives are not, which is exactly what makes it useful for APIs like Object.create or a property-walking helper.

Three lookalikes

TypeAcceptsUse it
objectany non-primitivewhen a primitive would be a bug
Objectalmost everything, primitives included (they box)never
{}anything except null and undefinedrarely; it means "not nullish", not "an object"

The capitalised Object is the boxed wrapper interface, and the handbook is blunt about it: don't use it. {} looks like an empty object type but is closer to a top type — const n: {} = 42 compiles.

What object does not give you

No index signature. You cannot write value.anything or value[key] on an object; only the members of Object.prototype are available. When you need keyed access, use Record<string, unknown> and validate, not object.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Typing a parameter that must be a reference value, such as a WeakMap key or an Object.create prototype
  • Rejecting accidentally passed primitives in a deep-merge or deep-clone helper
  • Explaining a legacy `Object` annotation in a declaration file before replacing it

Frequently asked questions

What is the difference between object, Object and {} in TypeScript?

`object` accepts any non-primitive value and rejects strings, numbers, booleans, symbols, bigints, null and undefined. `Object` is the boxed wrapper interface and accepts primitives too, so the handbook says never to use it. `{}` accepts every value except `null` and `undefined` — it means "not nullish", not "an empty object".

Why can't I index a value typed object?

Because `object` has no index signature — it only guarantees the value is non-primitive, so `value[key]` is an error. Use `Record<string, unknown>` when you need keyed access, then narrow each value with `typeof` before using it. `Object.keys`, `Object.values` and `Object.entries` still work on an `object`.

How do I type "an object with no properties" in TypeScript?

Use `Record<string, never>`, not `{}`. `{}` is effectively a top type that accepts numbers, strings and everything else non-nullish. `Record<string, never>` says every key maps to a value that cannot exist, so only `{}` as a literal satisfies it.

More examples

object versus Record for keyed access

Prints `2`, `3`, `0`. `object` tells you the value is non-primitive but gives no index signature, so `o[key]` is an error — only `Object.keys`/`values`/`entries` work. `Record<string, unknown>` is the type to reach for when you need to read arbitrary keys, and `unknown` values still force the `typeof` check.

Example · typescript
function sumValuesWrong(o: object): number {
  // o[k] here would be: Element implicitly has an 'any' type because
  // expression of type 'string' can't be used to index type 'object'.
  return Object.values(o).length;
}

function sumValues(o: Record<string, unknown>): number {
  let total = 0;
  for (const key of Object.keys(o).sort()) {
    const v = o[key];
    if (typeof v === "number") total += v;
  }
  return total;
}

console.log(sumValuesWrong({ a: 1, b: 2 }));
console.log(sumValues({ a: 1, b: 2, c: "skip" }));
console.log(sumValues({}));

The three lookalikes side by side

The map prints, in order, `object -> object type? true` twice, `function -> object type? true`, then `string`/`number` with `false`, then `null`. The three annotations below show the practical difference: only `object` rejects `"text"` and `42`; `{}` and `Object` accept both, which is why neither is a way to say "give me an object".

Example · typescript
const values: unknown[] = [{ a: 1 }, [1, 2], () => 0, "text", 42, null];

function classify(v: unknown): string {
  if (v === null) return "null";
  const t = typeof v;
  // matches what the `object` type accepts
  const isObjectType = t === "object" || t === "function";
  return `${t} -> object type? ${isObjectType}`;
}

console.log(values.map(classify));

const asObject: object = { a: 1 };   // ok
const asBrace: {} = "text";           // ok — {} is not "empty object"
const asObjectCap: Object = 42;       // ok — boxed wrapper, do not use
console.log(asObject, asBrace, asObjectCap);

Discussion

  • Be the first to comment on this lesson.