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

Static index signatures on classes are not inherited #50183

Open
WillsterJohnson opened this issue Aug 4, 2022 · 0 comments
Open

Static index signatures on classes are not inherited #50183

WillsterJohnson opened this issue Aug 4, 2022 · 0 comments
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript

Comments

@WillsterJohnson
Copy link

WillsterJohnson commented Aug 4, 2022

Bug Report

Related/potentially solved by:

When extending a class with an index signature, that signature is preserved on the children of the class for type safety. However if that signature is static, bye-bye type safety.

The same issue applies to all static members; the actual implementations are inherited, overrides are required with noImplicitOverride, however the type information from the parent class is discarded and must be redeclared.
I understand how the prototype chain plays into these issues with statics, but type information isn't on the prototype it's in TS, and we shouldn't deny valuable tools for the sake of mimicking JS prototype (which, let's be honest, can get a bit messy).

I'll leave it up to the team to decide if they want to group the above in with this static index signatures issue, or leave the above for another day - I'm not being effected by it but it's probably worth mentioning.

🔎 Search Terms

static index signature, index signature, not inherited, class signature

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about (N/A: no relevant FAQ)

⏯ Playground Link

Playground link with relevant code

💻 Code

// NON STATIC: no problems, works as intended

class HasSign {
    [key: string]: boolean;
    foo: string; // error is good: index signature is working
}
class ExtHasSign extends HasSign {
    foo: string; // error is good: index signature is inherited and working
}

// STATIC: very limited use (approaches non-useful), if works as intended I contest that intention

class HasStaticSign {
    static [key: string]: boolean;
    static foo: string; // error is good: index signature is working
}
class ExtHasStaticSign extends HasStaticSign {
    static foo: string; // no error is bad: index signature is NOT inherited and therefore NOT working
}

🙁 Actual behavior

Static index signature is discarded by typescript in child classes.
This gives static index signatures a very limited usability;

  • they can be used to remind yourself that the static members of your class (but not its children) must match a certain type
  • TS will infer any if you don't explicitly type the member with the same type from the static index signature

🙂 Expected behavior

Static index signature is inherited and reconciled in the same way non-static index signatures are, throwing errors on relevant, incorrect static properties/methods.
This would make static index signatures just as useful as their non-static counterparts. I think the static-ness of something shouldn't prevent it from providing type information, especially in places where it's actually being used.

Notable issues with Desired Solution

What if people want their code to work this way?
They don't want static index signatures to be inherited, just how things are currently. As I mentioned earlier, there are a very limited range of use cases for the current behavior, but breaking peoples code is a bad idea.
This kinda necessitates having two forms of signature, one inherited and one not. But then again, what if someone wants a non-static signature to not be inherited? We're dealing with a disparity between two features which ought to be similar but are actually very different.

A potential solution to this could be to hijack the Private/Protected signatures to behave differently. On the linked issue currently, there's 18 months of silence aside from my recent comment.
Maybe protected/private can have a different meaning on index signatures? Instead of meaning "the keys must be private for this signature to apply", it could mean "this signature itself is private, and should not be present on any child classes".

Another, more out-there idea is to build onto extends and implements with a signatures keyword. (bear with me on this, its odd, unlikely, but an interesting thought).
There are two possibilities here;

  • signatures is it's own standalone keyword which must be followed by one or more comma-separated interfaces/classes, who's index signatures (static or not) will be applied to the class (regardless of inheritance)
  • signatures modified extends by demanding that the index signatures (static or not) of the parent class will be applied to the child.
    This would actually be better in some ways than hijacking private/protected, as child classes could decide if they want the index signature or not, giving additional flexibility to the use of signatures and not forcing children to abide/not abide by an index signature should the child's author have different ideas.

Potential Workarounds

Explicitly redeclare the type signature.

Pros:

  • No runtime cost

Cons:

  • Lot's of work
  • Repetition
  • Zero guarantee of continutity; prone to user error

Verdict: Fail

Some variation of decorating with static interface

Pros:

  • Some guarantee of continuity

Cons:

  • Lot's of work
  • Repetition
  • Runtime cost of Decorator

Verdict: Fail

Typing a variable then assigning an anonymous class
Instantly loses all typing and ability to extend, Fail.

@RyanCavanaugh RyanCavanaugh added Suggestion An idea for TypeScript Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature labels Aug 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

2 participants