Repository: TypeScript
Issue: Static index signatures on classes are not inherited
Labels: Suggestion,Awaiting More Feedback

# Bug Report

Related/potentially solved by:
- #33892 
- #41652 

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, `override`s 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.
<!--
  Please fill in each section completely. Thank you!
-->

### 🔎 Search Terms

static index signature, index signature, not inherited, class signature
<!--
  What search terms did you use when trying to find an existing bug report?
  List them here so people in the future can find this one more easily.
-->

### 🕗 Version & Regression Information

<!-- When did you start seeing this bug occur?

"Bugs" that have existed in TS for a long time are very likely to be FAQs; refer to
  https://github.com/Microsoft/TypeScript/wiki/FAQ#common-bugs-that-arent-bugs

If possible, please try testing the nightly version of TS to see if it's already been fixed.
For npm: `typescript@next`
This is also the 'Nightly' version in the playground: http://www.typescriptlang.org/play/?ts=Nightly

Note: The TypeScript Playground can be used to try older versions of TypeScript.

Please keep and fill in the line that best applies:
-->
- This is the behavior in every version I tried, ~~and I reviewed the FAQ for entries about~~ (N/A: no relevant FAQ)

### ⏯ Playground Link

<!--
  A link to a TypeScript Playground "Share" link which shows this behavior

  The TypeScript Workbench can be used for more complex setups, try
  https://www.typescriptlang.org/dev/bug-workbench/

  As a last resort, you can link to a repo, but these will be slower for us to investigate.
-->
[Playground link with relevant code](https://www.typescriptlang.org/play?#code/PTAEDkHl1BlAVAgvAkgYQFygHYHtQAOATrgEYA2ApgLYDOANKAO65EDWtoAhpwJbYAXStgAmlEQFgAUNIDG5HpwASPWLwDm2UAG9pofaADabSgE8stAUX7qAullK5cVLtgDcegwDMnFqzbdQEFBKIhIiUF5OdScRLH4xAA9QWg1sLgEAVyJKSM4WdhtpAF85BVpOAFFEgRVaNU0QmuERZVU0nU99H1w-a2x1QODQ8LzQGNw4yNFKZNTNDOzcqOmAC1DeIRFuUWZWNiKpUpkpYIRkdCwAN1DTUHJeak3xUEzaXIAKLgJiXC5ZdacPDYAC0b0oXky5AAlIxeF49uxODxpkIZtsUKBZLhBJRLKABKsMqjhAJeDjpGVFKA6rABBleLIGlpdFIDCl6WTZEYTOYOf07A4nC53F0OQzuT0+gEgmARqwxhMpglZik0oscmMCgcBiUqRVQNVaqpOYzmU00a0aSaJebWezLBLQFL+TLgngQmEFStSFxlTM5uqspqVlB4GsNlsdttCaEIaxcmHETr1CUgA)

### 💻 Code

<!-- Please post the relevant code sample here as well-->
```ts
// 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

<!-- What happened, and why it was wrong -->
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

<!-- What you expected to happen instead, and why -->
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](https://github.com/microsoft/TypeScript/issues/41652) 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](https://stackoverflow.com/a/43674389/19686185)**

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](https://stackoverflow.com/a/40006145/19686185)**
Instantly loses all typing and ability to extend, Fail.