Skip to content

Make object type const with a keyword #61681

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
6 tasks done
jcubic opened this issue May 9, 2025 · 4 comments
Closed
6 tasks done

Make object type const with a keyword #61681

jcubic opened this issue May 9, 2025 · 4 comments

Comments

@jcubic
Copy link

jcubic commented May 9, 2025

🔍 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

⭐ Suggestion

See above

📃 Motivating Example

See above

💻 Use Cases

See above

@MartinJohns
Copy link
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
Copy link
Member

Duplicate #12936

@snarbles2
Copy link

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
Copy link
Author

jcubic commented May 9, 2025

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

@RyanCavanaugh RyanCavanaugh closed this as not planned Won't fix, can't repro, duplicate, stale May 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants