Consider the following code, which uses TypeScript language features introduced in v2.8 (conditional types):
type P<TObject, TPropertySuperType> = {
[K in keyof TObject]: TObject[K] extends TPropertySuperType ? K : never;
}[keyof TObject];
function g<
T,
K extends keyof Pick<T, P<T, string>>
>(obj: T, prop: K): void { }
class C {
public alpha: string;
public beta: number;
public f(): void {
g(this, "alpha"); // <-- does not compile!
g(this, "beta");
g<C, "alpha">(this, "alpha");
g<C, "beta">(this, "beta");
g(new C(), "alpha");
g(new C(), "beta");
this.g2("alpha");
this.g2("beta");
this.g2<"alpha">("alpha");
this.g2<"beta">("beta");
}
public g2<
K extends keyof Pick<C, P<C, string>>
>(prop: K) { }
}
The idea behind the type P
is that it selects the names of the properties of TObject
that satisfy the constraint that the type of the property extends TPropertySuperType
. The functions g
and g2
then use the type P
in a type parameter constraint, such that:
- You can only call
g
when theprop
parameter is the name of aextends string
-typed property ofobj
- You can only call
g2
when theprop
parameter is the name of aextends string
-typed property ofC
.
Here, because C.alpha
is of type string
and C.beta
is of type number
, I would expect all five invocations of g
/g2
with prop === "alpha"
to compile, and all five invocations with prop === "beta"
not to compile.
However, the invocation g(this, "alpha")
does not compile, as you can see if you paste this code into the TypeScript playground. The error is:
Argument of type '"alpha"' is not assignable to parameter of type 'this[keyof this] extends string ? keyof this : never'.
Why does this particular invocation fail? I'm guessing it has something to do with how TypeScript infers the type of this
, but the details are fuzzy to me.