Skip to content
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

Computed key in get, set declarations incorrectly reported as non-key type #51890

Closed
cefn opened this issue Dec 14, 2022 · 2 comments
Closed
Labels
Duplicate An existing issue was already created

Comments

@cefn
Copy link

cefn commented Dec 14, 2022

Bug Report

Use of a computed property name in a getter or setter leads to unexpected error A computed property name must be of type 'string', 'number', 'symbol', or 'any' even when the computed type does satisfy these types.

If this should be considered a feature report, (e.g. this is a known gap in the language, but just a misleading error) one motivating use case for improving the support of get and set could be achieving future strictness preventing readonly assigned to mutable.

In the short term (before readonly strictness), being able to use get with mapped types and computed property names and value types would mean that there are workarounds for cases when you want to PREVENT the passing of writeable objects and maybe warn that the object should have been readonly, as demonstrated in the imaginary Frozen<T> implementation in the code sample.

🔎 Search Terms

getter setter "computed property name"

🕗 Version & Regression Information

I don't know of a version this works with. Everything up to the Nightly at the time of writing experiences this bug.

⏯ Playground Link

Playground demonstrating error

💻 Code

// FIXED FIELDS - COMPILES

type HasFixedField = {
  propName:boolean
}

type HasFixedGetter = {
  get propName():boolean
}

type HasFixedSetter = {
  set propName(value:boolean)
}

// COMPUTED FIELDS - COMPILE ERROR

type HasGenericField<K extends string, V> = {
  [k in K]: V;
}

type HasGenericGetter<K extends string, V> = {
  get [k in K]() : V;
}

interface HasGenericSetter<K extends string, V> {
  set [k in K](value:V)
}

interface HasNoGenericSetter<K extends string>{
  set [k in K]:never
}

type Frozen<T> = keyof T extends string ? HasGenericGetter<keyof T, T[keyof T]> & HasNoGenericSetter<keyof T> : never

🙁 Actual behavior

Hovering over the error in the get or set definitions (which are identical to the working property definition above) leads to these errors...

A computed property name must be of type 'string', 'number', 'symbol', or 'any'.
Cannot find name 'k'
'K' only refers to a type, but is being used as a value here.

🙂 Expected behavior

I would expect it to be possible to define the presence and absence of getters and setters using computed property names.

@andrewbranch
Copy link
Member

This is all invalid syntax, which is leading to some red herrings in the error messages as the parser does its best to recover into a valid state. Computed property declarations are not the same thing as mapped types, though they both use square brackets to describe the type of a key in a resulting object type:

// mapped types
type T = { [K in SomeUnion]: any }
// Mapped types are not interfaces or object literal types!
// `[K in SomeUnion]: any` is not a property!
type U = {
  [K in SomeUnion]: any;
  foo: any; // <-- Syntax error!
}
// Mapped types support adding a `readonly` modifier to resulting keys:
type V = { readonly [K in SomeUnion]: any }
type W = { +readonly [K in SomeUnion]: any }
// Or removing `readonly` (only makes sense on homomorphic mapped types):
type X = { -readonly [K in keyof T]: T[K] }

// computed properties
type Y = {
  [someValue]: string; // <-- real property
  foo: number;
}
// they can equivalently go on interfaces
interface I {
  [someValue]: string;
  foo: number
}
// interface and object literal property declarations support
// `get` and `set` modifiers:
interface J {
  get [someValue]: string;
}

Syntax for what you’re looking for doesn’t exist because the semantics you want don’t exist. I think this is essentially a duplicate of #21759, and #13347 is very relevant as you’ve already found.

@andrewbranch andrewbranch added the Duplicate An existing issue was already created label Dec 19, 2022
@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

3 participants