Question

How to Type Object Literal Properties in TypeScript

Question

In TypeScript, class properties can have type annotations like this:

class ClassName {
  property: string;
}

How do you declare the type of a property in an object literal?

I tried this:

var obj = {
  property: string;
};

but it does not compile. TypeScript reports:

The name 'string' does not exist in the current scope

Am I using the wrong syntax, or is this a TypeScript bug?

Short Answer

By the end of this page, you will understand why property: string works in a class but not inside an object literal, and how to correctly type object literals in TypeScript using type annotations, inline object types, interfaces, and type inference.

Concept

In TypeScript, type annotations and object values use similar-looking syntax, but they appear in different places.

In a class body, this is a type annotation:

class ClassName {
  property: string;
}

Here, property is being declared as a class field, and string is its type.

But in an object literal, this syntax means something different:

var obj = {
  property: string
};

Inside an object literal, JavaScript expects property to be assigned a value. So TypeScript reads string as if it were a variable name or identifier, not a type. Since no variable named string exists, you get the error.

To type an object literal, you usually annotate the variable, not the property inside the literal value.

Example:

const obj: { property: string } = {
  property: "hello"
};

This tells TypeScript:

  • obj must be an object
  • that object must have a property
  • property must be a string

This matters because object literals are everywhere in TypeScript:

  • API request payloads
  • configuration objects
  • function arguments
  • return values
  • state objects in frontend apps

Understanding where types go helps you write valid TypeScript and avoid confusing syntax errors.

Mental Model

Think of it like this:

  • A class definition is like a blueprint, so you describe the shapes and types of parts.
  • An object literal is like the actual built item, so you must provide real values.

Blueprint example

class User {
  name: string;
}

You are saying: “A User has a name, and that name must be a string.”

Built object example

const user = {
  name: "Ada"
};

You are saying: “Here is the actual value for name.”

If you write this:

const user = {
  name: string
};

that is like trying to build the object but placing the word string where an actual value should go.

So the rule is:

  • Types go in declarations
  • Values go in object literals
Take Quiz

Syntax and Examples

Correct ways to type an object literal

1. Annotate the variable with an inline object type

const obj: { property: string } = {
  property: "hello"
};

This is the most direct equivalent to your class example.

2. Let TypeScript infer the type

const obj = {
  property: "hello"
};

TypeScript infers this as:

{ property: string }

This is often enough if the object is simple.

3. Use an interface

interface MyObject {
  property: string;
}

const obj: MyObject = {
  property: "hello"
};

This is useful when the same object shape is reused in multiple places.

4. Use a type alias

type MyObject = {
  property: string;
};

const obj: MyObject = {
  property: "hello"
};

5. Type a function parameter that expects an object literal

function printProperty(obj: { property: string }) {
  console.log(obj.property);
}

printProperty({ property: "hello" });

Incorrect syntax

const obj = {
  property: string
};

Why it fails:

  • property: inside an object literal means “assign a value to property”
  • string is treated as a variable name
  • there is no variable called string

Another valid pattern: assertion

const obj = {
  property: "hello"
} as { property: string };

This works, but beginners should usually prefer direct type annotations unless there is a specific reason to use as.

Step by Step Execution

Consider this example:

const obj: { property: string } = {
  property: "hello"
};

console.log(obj.property);

Step by step

  1. const obj: starts a variable declaration.
  2. { property: string } defines the expected shape of obj.
  3. TypeScript now expects obj to be an object with one property named property.
  4. That property must contain a string value.
  5. The object literal is checked:
{
  property: "hello"
}
  1. "hello" is a string, so it matches the required type.
  2. console.log(obj.property) is allowed because property is known to exist.

What if the value is wrong?

const obj: { property: string } = {
  property: 123
};

TypeScript reports an error because 123 is a number, not a string.

What if the property is missing?

const obj: { property: string } = {};

TypeScript reports an error because the required property is missing.

Real World Use Cases

Object literal typing is used constantly in real TypeScript code.

Configuration objects

const config: { apiUrl: string; timeout: number } = {
  apiUrl: "https://api.example.com",
  timeout: 5000
};

API payloads

type LoginRequest = {
  email: string;
  password: string;
};

const request: LoginRequest = {
  email: "user@example.com",
  password: "secret"
};

Function arguments

function createUser(user: { name: string; age: number }) {
  return `${user.name} is ${user.age}`;
}

createUser({ name: "Sam", age: 30 });

Frontend state objects

interface FormState {
  loading: boolean;
  message: string;
}

const state: FormState = {
  loading: false,
  message: "Ready"
};

Parsed data after validation

type Product = {
  id: number;
  title: string;
};

const product: Product = {
  id: 1,
  title: "Notebook"
};
Take Quiz

Real Codebase Usage

In real projects, developers usually do not write large inline object types everywhere. Instead, they combine a few common patterns.

Reusable interfaces and type aliases

When the same shape appears more than once:

interface User {
  id: number;
  name: string;
}

const currentUser: User = {
  id: 1,
  name: "Ava"
};

Function parameter typing

Object literals are often passed directly into functions:

function sendEmail(options: { to: string; subject: string }) {
  console.log(options.subject);
}

sendEmail({ to: "a@example.com", subject: "Welcome" });

Validation at boundaries

Developers often type expected object shapes when handling external input:

type EnvConfig = {
  mode: string;
  port: number;
};

Then they validate real data before treating it as that type.

Optional properties

Many real objects are partly optional:

interface Profile {
  username: string;
  bio?: string;
}

Readable extraction of complex types

Instead of this:

const settings: { theme: string; notifications: boolean; language: string } = {
  theme: "dark",
  notifications: true,
  language: "en"
};

teams often do this:

interface Settings {
  theme: string;
  notifications: boolean;
  language: string;
}

const settings: Settings = {
  theme: "dark",
  notifications: true,
  language: "en"
};

This is easier to reuse and maintain.

Common Mistakes

1. Putting a type where a value should be

Broken code:

const obj = {
  property: string
};

Why it fails:

  • string is treated as a variable, not a type

Fix:

const obj: { property: string } = {
  property: "hello"
};

2. Forgetting to provide an actual value

Broken code:

const obj: { property: string } = {
  property:
};

Fix:

const obj: { property: string } = {
  property: "hello"
};

3. Giving the wrong value type

Broken code:

const obj: { property: string } = {
  property: 42
};

Fix:

const obj: { property: string } = {
  property: "42"
};

4. Confusing type annotations with type assertions

const obj = { property: "hello" } as { property: string };

This works, but it is not the same as declaring the type in the object literal. Prefer clear annotations unless you need an assertion.

5. Overusing inline types

This is valid but can become hard to read:

const user: { id: number; name: string; email: string; isAdmin: boolean } = {
  id: 1,
  name: "Lee",
  email: "lee@example.com",
  isAdmin: false
};

Better:

interface User {
  id: number;
  name: string;
  email: string;
  isAdmin: boolean;
}

const user: User = {
  id: 1,
  name: "Lee",
  email: "lee@example.com",
  isAdmin: false
};

Comparisons

Class property typing vs object literal typing

ContextSyntaxMeaning
Class bodyproperty: string;Declares a property type
Object literalproperty: "hello"Assigns a value
Variable annotationconst obj: { property: string } = ...Declares the object's expected shape

Interface vs inline object type

OptionExampleWhen to use
Inline typeconst obj: { property: string } = ...Small one-off objects
Interfaceinterface MyObj { property: string }Reusable object shapes
Type aliastype MyObj = { property: string }Reusable shapes, unions, mapped types

Inference vs explicit typing

ApproachExampleProsCons
Inferenceconst obj = { property: "hello" }Less code, very commonLess explicit for learners
Explicit typeconst obj: { property: string } = { property: "hello" }Clear intentMore verbose

Annotation vs assertion

ApproachExampleNotes
Annotationconst obj: MyType = { ... }Safer and clearer
Assertionconst obj = { ... } as MyTypeUseful sometimes, but can hide mistakes
Take Quiz

Cheat Sheet

// Class property type
class MyClass {
  property: string;
}

// Object literal with inferred type
const obj1 = {
  property: "hello"
};

// Object literal with inline type annotation
const obj2: { property: string } = {
  property: "hello"
};

// Object literal using an interface
interface MyObject {
  property: string;
}

const obj3: MyObject = {
  property: "hello"
};

// Object literal using a type alias
type MyObjectType = {
  property: string;
};

const obj4: MyObjectType = {
  property: "hello"
};

Rules to remember

  • property: string; is valid in a type position such as a class, interface, or object type.
  • Inside an object literal, properties need actual values.
  • Type object literals by annotating the variable, parameter, or return type.
  • TypeScript can often infer object types automatically.

Common error

const obj = {
  property: string
};

Meaning of the error:

  • TypeScript thinks string is a variable name
  • it is not treated as a type there

Correct replacement

const obj: { property: string } = {
  property: "value"
};

FAQ

Why does property: string work in a class but not in an object literal?

Because a class body is a type declaration context, while an object literal is a value context. In an object literal, TypeScript expects a real value after the colon.

How do I type an object literal in TypeScript?

Usually by typing the variable:

const obj: { property: string } = { property: "hello" };

Can TypeScript infer the type automatically?

Yes. If you write:

const obj = { property: "hello" };

TypeScript infers property as a string.

Should I use an interface or an inline object type?

Use an inline type for small one-off cases. Use an interface or type alias when the shape is reused or becomes large.

Is this a TypeScript bug?

No. The syntax is being interpreted correctly. The problem is that string is being used where a value is required.

Can I type individual properties directly inside an object literal value?

Not with property: string syntax. You define the object's type outside the value, or let TypeScript infer it.

What is the cleanest beginner-friendly approach?

For learning, this is usually the clearest:

const obj: { property: string } = {
  property: "hello"
};
Take Quiz

Mini Project

Description

Build a small typed configuration object for an application. This demonstrates how to define the shape of an object literal correctly and how TypeScript checks each property value.

Goal

Create a TypeScript configuration object with explicit property types and use it in a function.

Requirements

  1. Create a type or interface for an app configuration object.
  2. The configuration must include a appName string, a port number, and a debug boolean.
  3. Create an object literal that matches that type.
  4. Write a function that accepts the configuration object and prints a message using its properties.
Take Quiz

Keep learning

Related questions

View more