The issue is that for class X {...}, The type of X.prototype is represented in TypeScript as X, the type of an instance of a class. From the (outdated but still relevant for this question) TypeScript Language Specification:
The type of the constructor function introduced by a class declaration is called the constructor function type. The constructor function type has the following members:
...[snip]...
- A property named 'prototype', the type of which is an instantiation of the class type with type Any supplied as a type argument for each type parameter.
So TypeScript thinks that the type of Hello.prototype is Hello. This is, of course, not true in general. It's true for methods, but not for instance properties, as you have discovered.
I searched through the issues in Github but didn't find anything mentioning this. It might be worth opening a new issue suggesting that the type of a class prototype be widened to only include methods.
EDIT: Whoopsie, I guess there are several existing issues about this, which were essentially declined suggestions because it would hurt more than it would help.
I know for a fact that doing so would mess up some stuff (currently an x instanceof Class check will narrow x's type to Class['prototype'], which, if widened to only include methods, would break everyone's code everywhere), so I doubt that they'd take such a suggestion. But it would be nice to have somewhere to point as official word on this issue.
Anyway, backing up to your problem... the runtime code is good, right? And you want this to work:
new Hello().k("a");
and would like a compiler warning on
new Hello().k("oopsie"); // error
? If so, then I'd suggest taking prototype out of the equation entirely and use a lookup type instead on the instance type Hello instead:
class Hello {
abc = {
a: 'l',
b: 1,
}
k = (prop: keyof Hello['abc']) => {
console.log(prop)
}
}
This now behaves as desired and is not exposing the weirdness around instance properties and class prototypes in TypeScript.
Okay, hope that helps. Good luck!