object
Matches any non-primitive value — objects, arrays and functions, but never a string or number.
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
| Type | Accepts | Use it |
|---|---|---|
object | any non-primitive | when a primitive would be a bug |
Object | almost everything, primitives included (they box) | never |
{} | anything except null and undefined | rarely; 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
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.
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".
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