Reputation: 849
I have the following code as a reduced example:
class QueryArgs {
studentId?: string;
teacherId?: string;
}
class BaseValidator<T> {
protected args: T;
constructor(args: T) {
this.args = args;
}
protected requireTeacher(): void {
if (!this.args.teacherId) {
throw new Error("teacherId required");
}
}
}
class QueryValidator extends BaseValidator<QueryArgs> {
public validateAdmin(): QueryArgs {
this.requireTeacher();
return this.args;
}
}
// Recreated implementation from a third party library
const args: QueryArgs = new QueryArgs();
args.studentId = "XXXX-XXX-XXX";
// Not the actual implementation just for illustration
const validator = new QueryValidator(args);
const validArgs = validator.validateAdmin();
The problem that I am having is in the BaseValidator
class in the requireTeacher
method this.args.teacherId
has the error Property 'teacherId' does not exist on type 'T'
.
I am not sure what I am missing in the generics part of Typescript.
Ideally TS would know in the BaseValidator
that the args
is an instance of QueryArgs
.
Thanks in advance!
Upvotes: 2
Views: 7726
Reputation: 2425
You need to further constrain the generic type argument T
to a type that has a teacherId
property. The way it is now, any type can be passed as T
, which means you can't assume that T
has teacherId
.
To constrain the type, try changing class BaseValidator<T>
to class BaseValidator<T extends QueryArgs>
. This restricts T
to types that extends QueryArgs
so that you're guaranteed that T
has a teacherId
property.
Check out this article where it mentions constraining generic arguments using extends
: https://www.typescriptlang.org/docs/handbook/generics.html
Upvotes: 4