In TypeScript, there are cases where you want to define a type that ensures an object contains at least one specific property, while allowing any additional properties.
A common example is ensuring an object has a name
property, regardless of what else it contains.
Basic Use Case
To specify that an object must have at least a name
property:
interface HasName {
name: string;
}
function greet(obj: HasName) {
console.log(`Hello, ${obj.name}`);
}
greet({ name: "Alice", age: 30 }); // ✅ Works
Using Inline Types
Instead of declaring a separate interface:
function greet(obj: { name: string }) {
console.log(`Hi, ${obj.name}`);
}
This also works fine for inline use.
Using Generics with Constraints
If you're working with generics and want to retain the full object type while requiring a name
property:
function greet<T extends { name: string }>(obj: T) {
console.log(`Hi, ${obj.name}`);
}
This keeps the full shape of the passed object available for further use.
Dynamic Check with Type Predicate
Sometimes you receive unknown data and want to ensure it has a name
property:
function hasName(obj: any): obj is { name: string } {
return typeof obj === 'object' && obj !== null && 'name' in obj;
}
Used like:
const data = { name: "Bob", age: 40 };
if (hasName(data)) {
console.log(data.name); // Safe access
}
Summary
To enforce the presence of a property like name
:
- ✅ Use a basic interface like
{ name: string }
- ✅ Use generics for flexibility and type retention
- ✅ Use type predicates for runtime checks
- 🔐 TypeScript won't automatically enforce "only one property", but it ensures required keys exist
This pattern is useful in APIs, forms, and anywhere you want to enforce structure while still allowing flexibility.
Top comments (1)
This doesn't work:
TypeScript throws the following error:
The inline typing also doesn't work; it throws the same error.