Skip to content

Make object type const with a keyword #61681

Not planned
Not planned
@jcubic

Description

@jcubic

🔍 Search Terms

The idea came from this Twitter discussion:

https://x.com/Cal_Irvine/status/1920844023507325084

about this code:

const obj = { foo: 10, bar: 20 } as const;

const keys = Object.keys(obj); 

and why keys is of type string[]

I understand that obj can be extended, like in this example:

type MyArgumentObj = {foo: () => void, bar: () => void}

function callThing(input: MyArgumentObj ) {
    (Object.keys(input) as (keyof typeof input)[]).forEach((key) => input[key]())
}

const myObj = {
    foo: () => undefined,
    bar: () => undefined,
    extraProp: 'Some metadata'
} as const

callThing(myObj);

This is more of a question that only designers of the language can answer. So this is not something for StackOverflow and I don't see any other place with discussions.

Why not adding a keyword that make the type input: MyArgumentObj only accept object with the same shape and make sure that it's properly type checked in the whole codebase and not extended

Something like:

type MyArgumentObj = { foo: 10, bar: 20 } is const;

function callThing(input: MyArgumentObj ) {
}

const myObj = {
    foo: () => undefined,
    bar: () => undefined,
    extraProp: 'Some metadata'
};

callThing(myObj);

That will be a type error. If this was implemented, Object.keys() could return ('foo' | 'bar')[] as a lot people would expect and complain about. And this const type could be added to this object as well:

const obj = { foo: 10, bar: 20 } as const;

const keys = Object.keys(obj); // keys will be ('foo' | 'bar')[]

And every code that mutate the object with this type should throw type error.

I'm not sure if this is doable or what are the limitations, so this is more of a question why it's not possible?

Of course the syntax can be different.

✅ Viability Checklist

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
    This wouldn't change the runtime behavior of existing JavaScript code
    This could be implemented without emitting different JS based on the types of the expressions
    This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
    This isn't a request to add a new utility type: https://github.com/microsoft/TypeScript/wiki/No-New-Utility-Types
    This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals

⭐ Suggestion

See above

📃 Motivating Example

See above

💻 Use Cases

See above

Activity

MartinJohns

MartinJohns commented on May 9, 2025

@MartinJohns
Contributor

Object.keys(obj) is intentionally returning string[], because objects are not sealed. They can contain more properties than keyof T. There are numerous issue about this, just search for "object.keys".

RyanCavanaugh

RyanCavanaugh commented on May 9, 2025

@RyanCavanaugh
Member

Duplicate #12936

snarbles2

snarbles2 commented on May 9, 2025

@snarbles2

Why not adding a keyword that make the type input: MyArgumentObj only accept object with the same shape and make sure that it's properly type checked in the whole codebase and not extended

Sounds similar to Exact Types. The problem is if you don't have comprehensive exact types support, there is no shortage of ways of accidentally extending your non-extensible object.

type MyArgumentObj = { foo: 10, bar: 20 } is const;

function callThing(input: MyArgumentObj ) {
}

function mutator(victim: {foo: number, bar: number, baz?: number}) {
    victim.baz = 0xdeadbeef;
}

const myObj = {
    foo: 10 as const,
    bar: 20 as const,
};

mutator(myObj); // uh-oh
callThing(myObj);
jcubic

jcubic commented on May 9, 2025

@jcubic
Author

@RyanCavanaugh Yes it seems this is what I request here. Pretty shame that this feature request is hanging since 2016.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @jcubic@MartinJohns@RyanCavanaugh@snarbles2

        Issue actions

          Make object type const with a keyword · Issue #61681 · microsoft/TypeScript