π Search Terms
Object.hasOwn narrowing
Object.hasOwn key narrowing
hasOwn keyof
hasOwn property type guard
hasOwn own property narrowing
Object.hasOwn Record
Object.hasOwn unknown object
hasOwnProperty narrowing
β
Viability Checklist
β Suggestion
I would like TypeScript to improve control-flow narrowing when using Object.hasOwn(obj, key).
Object.hasOwn() is the modern standard JavaScript API for checking whether an object has an own property. However, after checking Object.hasOwn(obj, key), TypeScript does not always narrow the relationship between obj and key in a way that makes safe property access ergonomic.
The suggestion is for TypeScript to treat successful Object.hasOwn(obj, key) checks similarly to a built-in type guard, where possible.
For example, inside this block:
if (Object.hasOwn(obj, key)) {
// TypeScript should know that `key` is an own key of `obj`
}
TypeScript could narrow key relative to obj, or narrow obj to include the checked property when the key is a string/number/symbol literal or a narrowed union.
π Motivating Example
When working with data from APIs, dashboards, configuration objects, or dictionaries, developers often need to check whether a dynamic key exists before accessing it.
Today, the runtime check is clean:
const labels = {
pending: "Pending",
approved: "Approved",
rejected: "Rejected",
} as const;
function getLabel(status: string) {
if (Object.hasOwn(labels, status)) {
return labels[status];
// Currently this can still produce an error because `status`
// is still just `string`, not narrowed to keyof typeof labels.
}
return "Unknown";
}
Developers know this is safe at runtime, because Object.hasOwn(labels, status) verifies that the property exists. But TypeScript does not fully use that information for narrowing.
A more ergonomic behavior would be:
function getLabel(status: string) {
if (Object.hasOwn(labels, status)) {
// status is narrowed to keyof typeof labels
return labels[status];
}
return "Unknown";
}
### π» Use Cases
### 1. What do you want to use this for?
I want to use `Object.hasOwn()` as the standard way to safely narrow dynamic object keys before property access.
Common examples include:
- mapping backend enum/status values to UI labels
- reading configuration objects
- validating API response fields
- checking feature flags
- accessing dictionary-style objects
- working with `Record<string, unknown>` or partially known objects
Example:
```ts
const statusLabels = {
active: "Active",
blocked: "Blocked",
pending: "Pending",
} as const;
function formatStatus(status: string) {
if (Object.hasOwn(statusLabels, status)) {
return statusLabels[status];
}
return "Unknown";
}
2. What shortcomings exist with current approaches?
Currently, developers often need to use extra assertions or custom helper functions:
if (Object.hasOwn(statusLabels, status)) {
return statusLabels[status as keyof typeof statusLabels];
}
or
function hasOwn<T extends object, K extends PropertyKey>(
obj: T,
key: K
): key is K & keyof T {
return Object.hasOwn(obj, key);
}
then use:
if (hasOwn(statusLabels, status)) {
return statusLabels[status];
}
This works, but it forces every project to define its own wrapper around a standard JavaScript API.
3. What workarounds are you using in the meantime?
- type assertions with as keyof typeof obj
- custom hasOwn type guard helpers
- switching to Map in places where plain objects are otherwise enough
- using in, although in checks the prototype chain and is not equivalent to Object.hasOwn()
The preferred runtime API is already Object.hasOwn(), so it would be useful if TypeScript's control-flow analysis understood it more directly.
π Search Terms
Object.hasOwn narrowing
Object.hasOwn key narrowing
hasOwn keyof
hasOwn property type guard
hasOwn own property narrowing
Object.hasOwn Record
Object.hasOwn unknown object
hasOwnProperty narrowing
β Viability Checklist
β Suggestion
I would like TypeScript to improve control-flow narrowing when using
Object.hasOwn(obj, key).Object.hasOwn()is the modern standard JavaScript API for checking whether an object has an own property. However, after checkingObject.hasOwn(obj, key), TypeScript does not always narrow the relationship betweenobjandkeyin a way that makes safe property access ergonomic.The suggestion is for TypeScript to treat successful
Object.hasOwn(obj, key)checks similarly to a built-in type guard, where possible.For example, inside this block:
TypeScript could narrow key relative to obj, or narrow obj to include the checked property when the key is a string/number/symbol literal or a narrowed union.
π Motivating Example
When working with data from APIs, dashboards, configuration objects, or dictionaries, developers often need to check whether a dynamic key exists before accessing it.
Today, the runtime check is clean:
Developers know this is safe at runtime, because Object.hasOwn(labels, status) verifies that the property exists. But TypeScript does not fully use that information for narrowing.
A more ergonomic behavior would be:
2. What shortcomings exist with current approaches?
Currently, developers often need to use extra assertions or custom helper functions:
or
then use:
This works, but it forces every project to define its own wrapper around a standard JavaScript API.
3. What workarounds are you using in the meantime?
The preferred runtime API is already Object.hasOwn(), so it would be useful if TypeScript's control-flow analysis understood it more directly.