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:
objmust be an object- that object must have a
property propertymust be astring
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
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 toproperty”stringis 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
const obj:starts a variable declaration.{ property: string }defines the expected shape ofobj.- TypeScript now expects
objto be an object with one property namedproperty. - That property must contain a string value.
- The object literal is checked:
{
property: "hello"
}
"hello"is a string, so it matches the required type.console.log(obj.property)is allowed becausepropertyis 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"
};
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:
stringis 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
| Context | Syntax | Meaning |
|---|---|---|
| Class body | property: string; | Declares a property type |
| Object literal | property: "hello" | Assigns a value |
| Variable annotation | const obj: { property: string } = ... | Declares the object's expected shape |
Interface vs inline object type
| Option | Example | When to use |
|---|---|---|
| Inline type | const obj: { property: string } = ... | Small one-off objects |
| Interface | interface MyObj { property: string } | Reusable object shapes |
| Type alias | type MyObj = { property: string } | Reusable shapes, unions, mapped types |
Inference vs explicit typing
| Approach | Example | Pros | Cons |
|---|---|---|---|
| Inference | const obj = { property: "hello" } | Less code, very common | Less explicit for learners |
| Explicit type | const obj: { property: string } = { property: "hello" } | Clear intent | More verbose |
Annotation vs assertion
| Approach | Example | Notes |
|---|---|---|
| Annotation | const obj: MyType = { ... } | Safer and clearer |
| Assertion | const obj = { ... } as MyType | Useful sometimes, but can hide mistakes |
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
stringis 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"
};
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
- Create a type or interface for an app configuration object.
- The configuration must include a
appNamestring, aportnumber, and adebugboolean. - Create an object literal that matches that type.
- Write a function that accepts the configuration object and prints a message using its properties.
Keep learning
Related questions
@Directive vs @Component in Angular: Differences, Use Cases, and When to Use Each
Learn the difference between @Directive and @Component in Angular, including use cases, examples, and when to choose each.
Accessing Input Value from EventTarget in TypeScript
Learn why EventTarget has no value property in TypeScript and safely read values from HTML input events in Angular applications.
Angular (change) vs (ngModelChange): What’s the Difference?
Learn the difference between Angular (change) and (ngModelChange), when each fires, and which one to use in forms and inputs.