I'm defining a _wrap
method on a base class, that modifies methods on derived classes.
class Base {
//this is the signature I'm working out
_wrap(key: unknown) {
const fn = this[key]
//I want typeof fn to be "Function"
//which is not callable
fn()
}
}
class Derived extends Base {
constructor() {
super()
//I want _wrap1 to require "isAFunction1 | isAFunction2"
super._wrap("isAFunction1")
}
isAFunction1() { }
isAFunction2() { }
notAFunction = "some value"
}
I'm struggling to write the type signature of this method such that it:
- Prevents calling
_wrap
from derived classes with keys that don't correspond to functions on the derived class - Allows me to use
this[key]
inside_wrap
as the appropriate type without casting
I can use _wrap(key: keyof typeof this)
to achieve #1, but not #2.
I feel like this related question should work. I don't understand why, but it doesn't meet either requirement - see the code playground here.
type KeysMatching<T, V> = {[K in keyof T]-?: T[K] extends V ? K : never}[keyof T];
class Base {
_wrap(key: KeysMatching<typeof this, Function>) {
const fn = this[key]
//I expect typeof fn to be "Function", but it's not, it's this[KeysMatching<this, Function>],
//which is not callable
fn()
}
}
class Derived extends Base {
constructor() {
super()
//I expect _wrap1 to expect "isAFunction1 | isAFunction2", but it's not, it's
//this[KeysMatching<this, Function>], which doesn't match string
this._wrap("isAFunction1")
}
isAFunction1() { }
isAFunction2() { }
notAFunction = "some value"
}
Is there a way to write this signature to achieve both these goals?
(Note: This is probably not ideal code in the first place. I'm annotating an existing library and not making code changes.)