Skip to content

Suggestion: a way to disable type widening in object literals #20195

Closed
@pelotom

Description

@pelotom

I understand the use of type widening with let and var variables (I use const ubiquitously so this is never a problem). But with object literals I pretty much never want the fields to be widened, and yet that's the default behavior:

const o = { x: 3 }; // inferred type is { x: number }

The only way I know of to work around this is with casts or type annotations, or by passing the object literal immediately to a function expecting the narrower type, thereby guiding type inference (although if the literal is being returned from a function even that technique won't work).

This is an eternal headache and it crops up in so many places. Would it be possible to add a compiler flag that makes it so that object literals don't get widened? I'm happy to be responsible for adding type annotations in the extremely rare cases where I actually want the widened type.

Edit

It looks like compiler flags are generally frowned upon to solve this problem, so let me amend my suggestion to take account of the discussion below. @mhegazy says,

We have talked in the past about a readonly modifier on property declarations.. e.g.

const o = { readonly x: 3 }; 

this allows the compiler to understand the intent of this object literal property, and not widen.

This would certainly be handy, but on its own it's still not ideal because one ends up writing readonly in a lot of places. Take for example CSS-in-JS objects, which involve many properties whose types are unions of string literals. Every single one of those properties needs to then be marked readonly in order to defeat the scourge of type widening. But if one could declare an entire object literal to have only read-only properties like so:

const o = readonly { x: 3, y: 'hello' };
// o: { readonly x: 3; readonly y: 'hello' }

now this starts to look like a workable solution! So, let this be my amended suggestion: readonly modifiers for both object literal properties as well as object literals themselves, which has the side effect of disabling type widening.

To the argument that readonly and type-widening are separate concerns and should be treated independently, to some extent I agree, but I also feel they are related; this is why the let vs. const rules for type widening exist, and I think that rationale makes sense. I also personally don't mind conflating readonly and type narrowing, because I prefer immutable objects everywhere too, so a syntax like

const o = readonly { x: 3, y: 'hello' };

would be attractive because it kills 2 birds with one stone. I currently don't use the readonly keyword much (even though in spirit I want everything to be read-only) because the cost-benefit ratio of annotating every single property in every single object literal is too high.

Metadata

Metadata

Assignees

No one assigned

    Labels

    CommittedThe team has roadmapped this issueSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions