Justin Ober
Justin Ober

Reputation: 849

Typescript: Generic type in base class

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

Answers (1)

John
John

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

Related Questions