Consider following code: palyground
class A {
private z = 0
}
type K = "z"
type ValidKeys = A[K] extends any ? K : never
Type ValidKeys
compiles fine and becomes the same as K
only if K
is some subset of keys of A
. And doesn't compile if I try to add anything else to K
like
type K = "z" | "not-a-key"
That's exactly the behavior that I need, but I want to make ValidKeys
generic depending on A
and K
:
type ValidKeys<A, K> = ...
How can I make such type?
Why do I need it?
I'm using mobx and its documentation says:
- By default TypeScript will not allow you to annotate private fields. This can be overcome by explicitly passing the relevant private fields as generic argument, like this:
makeObservable<MyStore, "privateField" | "privateField2">(this, { privateField: observable, privateField2: observable })
So I need to pass a type containing some private keys to generic function. If I just pass a literal, code will compile after renaming the property and will break at runtime.
So instead of
constructor() {
makeObservable<Store, "x" | "y">(this, { x: observable, y: false })
}
I want to write
constructor() {
makeObservable<Store, ValidKeys<Store, "x" | "y">>(this, { x: observable, y: false })
}
so that it would break at compile-time if the key is renamed.
The only way I found is explicitly write a snippet inside of my constructor:
constructor() {
type ExtraKeys = "x" | "y"
type _CompilesIfOk_ExtraKeys = Store[ExtraKeys]
makeObservable<Store, ExtraKeys>(this, { x: observable, y: false })
}
And want to simplify it and move into some helper.