A TypeScript object type lists the properties an object has and the type of each: { name: string; age: number }. Add ? to make a property optional and readonly to stop it from being reassigned. Write the type inline, or name it with type or interface to reuse it.
Writing Object Types
Properties are separated by ; or , (both work, ; is the usual style), and a line break is enough on its own. An inline type is fine for a one-off parameter; for anything used twice, give it a name.
// Inline, in a parameter
function area(rect: { width: number; height: number }): number {
return rect.width * rect.height;
}
// Named with a type alias
type Rect = { width: number; height: number };
// Named with an interface (the same shape)
interface RectShape {
width: number;
height: number;
}
type and interface describe object shapes equally well. The differences (declaration merging, unions) are covered on the interface vs type page.
Accessing a property the type does not declare is a compile error: point.z gives TS2339, Property 'z' does not exist on type '{ x: number; y: number; }'.
Optional Properties
A ? after the name lets the property be left out. Reading an optional property gives T | undefined, so TypeScript makes you handle the missing case before using it.
Calling a method on an optional property without a check is an error: p.nickname.toUpperCase() fails with TS18048, 'p.nickname' is possibly 'undefined'. Use optional chaining (p.nickname?.toUpperCase()) when undefined is an acceptable result.
prop?: T and prop: T | undefined are not the same. The first allows the key to be absent; the second requires the key, though its value may be undefined:
Readonly Properties
readonly stops reassignment of a property after the object is created. It is a compile-time check only, and it is shallow: an object or array stored in a readonly property can still be changed inside.
The output shows both limits: the id really changed at runtime (only the compiler knew it was readonly), and the array inside was modified. For a readonly array use readonly string[]; to make every property readonly at once, use Readonly<Order>.
Excess Property Checks
When you assign an object literal directly to a typed variable or pass it straight to a typed parameter, TypeScript rejects any property the type does not declare. Extra properties in a fresh literal are almost always typos.
index.ts(8,8): error TS2561: Object literal may only specify known properties, but 'colour' does not exist in type 'Options'. Did you mean to write 'color'?
The code is TS2561 because the compiler found a close match; an extra property with no similar name gives TS2353, Object literal may only specify known properties, and 'z' does not exist in type 'Point'. Without the check, the typo would compile, color would be undefined, and the program would silently draw in black. The check applies only to fresh literals. An object that already lives in a variable may carry extra properties, because TypeScript's typing is structural: a value fits a type when it has at least the required properties.
Nested Objects and Methods
Object types nest, and they can describe methods with either method syntax or a function-typed property.
For deep or reused shapes, name the inner type (type Address = { ... }) and reference it, or pull it out of the outer type with an indexed access, Company["address"], as the last lines do.
object vs {} vs Object
Three types sound alike and mean different things:
| Type | Accepts | Rejects |
|---|---|---|
object | any non-primitive: {}, [], functions, class instances | 5, "a", true, null, undefined |
{} | any value except null and undefined, primitives included | null, undefined |
Object | the same as {}, plus a check that built-in members like toString keep compatible types | null, undefined |
{ x: number } | any value with a numeric x | values without x |
{} does not mean "an empty object"; it means "not null or undefined". To accept any object with unknown keys, use Record<string, unknown>; for a map of keys to values, use an index signature or Record as shown on the dictionary page. Most of the time, a specific shape is better than any of the three.
Frequently Asked Questions
How do you define an object type in TypeScript?
List the properties and their types in braces: { name: string; age: number }. You can write it inline in an annotation, or give it a name with type User = { ... } or interface User { ... } and reuse it. Separate properties with ; or ,.
How do you make a property optional in TypeScript?
Put ? after the property name: { name: string; nickname?: string }. The object may leave nickname out, and reading it gives string | undefined, so you must check it or provide a default (user.nickname ?? user.name) before using it as a string.
What is the difference between prop?: string and prop: string | undefined?
prop?: string and prop: string | undefined?With prop?: string the key can be left out entirely. With prop: string | undefined the key is required, though its value may be undefined, so {} is a compile error. Reading either gives string | undefined.
What is the difference between object, {} and Object in TypeScript?
object means any non-primitive value (objects, arrays, functions) and rejects 5 or "a". {} means any value except null and undefined, including primitives. Object is almost the same as {} but also checks that built-in methods like toString keep compatible types. Use object, or better a specific shape, rather than {} or Object.
Why does TypeScript complain that an object literal may only specify known properties?
That is the excess property check: error TS2353, or TS2561 when the compiler can suggest the property you probably meant. When you assign a fresh object literal directly to a typed variable or parameter, any property the type does not declare is flagged, because it is usually a typo. Assigning an object stored in another variable skips the check, since extra properties are allowed by structural typing.