I devised a protective measure for a generic class to securely utilize its generic member.
The key in determining the type of the member is by inspecting the parent's type
attribute.
In the given code snippet, I leverage the type
attribute to ascertain the body type.
From external to the class, I can make use of the type guard and safely retrieve the data member.
However, when utilized within an instance method on this
, compilation errors arise (refer to the comments in the code for precise messages in each scenario).
What could be causing this issue? Are there constraints on narrowing down the type of the this
parameter?
type BodyType1 = {
field: string;
}
type BodyType2 = number[];
type BodyType = BodyType1 | BodyType2;
function isBodyType1(t: Message): t is Message<BodyType1> {
return t.type === 1;
}
function isBodyType2(t: Message): t is Message<BodyType1> {
return t.type === 2;
}
class Message<T extends BodyType = BodyType> {
type: number;
body: T;
constructor(type: number, body: T) {
this.type = type;
this.body = body;
}
getBodyField() {
const t = this;
if (isBodyType1(t)) {
// As per compiler hint: const t: this & Message<BodyType1>
return t.body.field; // Compiler error: Property 'field' does not exist on type 'T'.ts(2339)
}
if (isBodyType2(t)) {
// According to the compiler hint: const t: this & Message<BodyType1>
return t.body[0]; // Compiler error: Property 'Body' does not exist on type 'never'.ts(2339)
}
}
}
const m = new Message(1, {field: 'value'})
if (isBodyType1(m)) {
// This compiles
console.log(m.body.field);
}
if (isBodyType2(m)) {
// This also compiles
console.log(m.body[0]);
}