Parameter Properties
Parameter Properties
Level 10 — Classes & OOP in TypeScript A syntactic sugar shorthand in TypeScript that allows you to declare and initialize a class property in a single location: directly inside the constructor signature.
1. Prerequisites
- Classes Overview — The standard, verbose way of initializing properties.
- Access Modifiers (
public,private,protected) — The keywords required to trigger this shorthand.
2. Term Category
Object-Oriented Programming (Constructor Parameter Shorthand): Parameter properties implicitly declare and initialize class member fields directly within constructor parameter declarations.
3. Explanation
Environment Context
- Compile-Time (Compiles to standard JS property assignment)
(1) Design Motivation — "Why did we design this?"
Look at a standard TypeScript class. You have to write the word name four different times just to assign it!
- Declare the property:
name: string; - Define the constructor parameter:
constructor(name: string) - Use it in the assignment:
this.name = ... - Use it as the value:
... = name;
// The Verbose Way
class User {
public name: string;
private age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
This violates DRY and creates massive boilerplate. TypeScript introduced Parameter Properties to collapse all four steps into one.
(2) The Shorthand Syntax
If you place an Access Modifier (public, private, protected) OR the readonly keyword directly in front of a constructor parameter, TypeScript will automatically declare the property and assign the value to this under the hood!
// The Shorthand Way (Identical behavior to the code above!)
class User {
constructor(public name: string, private age: number) {
// Look, no body needed! TS automatically does `this.name = name`
}
}
(3) Mixing Standard and Parameter Properties
You can mix regular parameters and Parameter Properties in the same constructor.
class Config {
constructor(
public id: string, // Creates `this.id`
private key: string, // Creates `this.key`
tempData: any // Standard parameter. Does NOT create `this.tempData`
) {
console.log(tempData);
}
}
4. Common Mistakes & Pitfalls
Mistake 1: Forgetting public
The mistake: A developer loves the shorthand, so they write:
class Car {
constructor(brand: string) {}
}
const c = new Car("Ford");
console.log(c.brand); // ❌ Error: Property 'brand' does not exist on type 'Car'.
Why it's wrong: To trigger the magic shorthand, you MUST include an access modifier (public/private/protected) or readonly. If you omit them, TS treats brand as a standard, temporary function argument that is thrown away as soon as the constructor finishes running.
Golden Rule: Even if a property is public (which is the default), you MUST explicitly write the word public in the constructor to trigger the Parameter Property shorthand.
Mistake 2: Re-Declaring Class Field Properties when Using Constructor Parameter Properties
The mistake: Declaring name: string; at class root AND constructor(public name: string) (TS1086).
Why it's wrong: Adding public, private, protected, or readonly to constructor parameters automatically declares AND initializes the field. Re-declaring at class root causes duplicate member declarations.
Incorrect:
class User {
// name: string; // ❌ Duplicate identifier 'name'
constructor(public name: string) {}
}
Fix:
class User {
constructor(public name: string) {} // Declares and assigns this.name automatically!
}
Mistake 3: Expecting Parameter Properties Without Access Modifiers to Create Fields
The mistake: Writing constructor(name: string) expecting this.name to be automatically created.
Why it's wrong: Parameter property shorthand requires an explicit modifier (public, private, protected, or readonly). Without a modifier, it is a standard local parameter.
Incorrect:
class User {
constructor(name: string) {
// this.name is NOT created automatically without access modifier!
}
}
Fix:
class User {
constructor(public name: string) {} // Access modifier triggers field creation
}
5. Practice Exercises
Exercise 1: Refactoring Verbose Class Constructors to Parameter Properties
Scenario: Refactor a verbose class constructor into clean parameter properties shorthand syntax.
Requirements:
- Use
public,private, orreadonlyinside constructor parameter lists.
Answer
Implementation
// ❌ VERBOSE CLASS:
// class User {
// public name: string;
// private age: number;
// constructor(name: string, age: number) {
// this.name = name;
// this.age = age;
// }
// }
// ✅ CLEAN PARAMETER PROPERTIES SHORTHAND:
class User {
constructor(
public name: string,
private age: number,
public readonly id: string
) {}
}
const u = new User("Alice", 30, "usr_1");
console.log(u.name); // "Alice"
Technical Explanation
- Prefixing constructor parameters with access modifiers (
public,private,protected,readonly) automatically declares and initializes member fields. - Eliminates redundant field declarations and
this.field = fieldassignment boilerplate. - Significantly reduces visual noise in class definitions.
Exercise 2: Transpiled JavaScript Output Analysis
Scenario: Inspect transpiled JavaScript code generated from parameter properties shorthand.
Requirements:
- Show TS parameter properties source vs transpiled JS output.
Answer
Implementation
// TypeScript Source:
class Item {
constructor(public title: string, private price: number) {}
}
// Transpiled Output (JS):
class Item {
constructor(title, price) {
this.title = title;
this.price = price;
}
}
Technical Explanation
tscautomatically expands parameter properties into field initializations inside the generated JS constructor.- Access modifiers are stripped completely during compilation.
- Zero runtime performance penalty.
Exercise 3: Auditing Parameter Property Modifier Omission Bugs
Scenario: Explain why omitting access modifiers in constructor parameters converts them back into standard local arguments.
Requirements:
- Show why
constructor(title: string)does NOT create a class fieldtitle.
Answer
Implementation
class Widget {
// ❌ Does NOT create a class field 'title'! It is just a local constructor argument!
constructor(title: string) {}
}
const w = new Widget("My Widget");
// console.log(w.title); // ❌ Compile Error: Property 'title' does not exist on type 'Widget'.
Technical Explanation
- Parameter property shorthand requires an EXPLICIT modifier (
public,private,protected, orreadonly). - Parameters without modifiers are treated as temporary local variables scoped strictly to the constructor body.
- Common beginner oversight when using constructor shorthand.
6. Related Terms
- Classes Overview — The parent topic.
- Access Modifiers (
public,private,protected) — The trigger for this feature.
7. Key Takeaways
- Parameter Properties are a shorthand syntax to remove boilerplate when initializing class properties.
- Prefixing a constructor parameter with
public,private,protected, orreadonlyautomatically declares that property on the class and assigns the argument tothis.property. - It collapses declaration, parameter definition, and assignment into a single line.
- If you forget the modifier, it remains a standard function argument and will not be attached to the class instance.