[Typescript] Typing Class method with this keyword

We have the following code:

class Form<TValues> {
  error?: string;

  constructor(
    public values: TValues,
    private validate: (values: TValues) => string | void,
  ) {}

  isInvalid() {
    const result = this.validate(this.values);

    if (typeof result === "string") {
      this.error = result;
      return true;
    }

    this.error = undefined;
    return false;
  }
}

const form = new Form(
  {
    username: "",
    password: "",
  },
  (values) => {
    if (!values.username) {
      return "Username is required";
    }

    if (!values.password) {
      return "Password is required";
    }
  },
);

if (form.isInvalid()) {
  type test1 = Expect<Equal<typeof form.error, string>>; // error: (property) Form<TValues>.error?: string | undefined
} else {
  type test2 = Expect<Equal<typeof form.error, string | undefined>>;
}

 

We want to type isInvalid function, but somehow it doesn't have any arguement. 

One way is using this:

 isInvalid(): this is Form<TValues>

Since it check invalid case, we can do:

isInvalid(): this is Form<TValues> & { error: string } {

This actually solve the issue.

 

Another way we can do it is:

  isInvalid(): this is this & { error: string } {

So second thisis actually the Form<TValues>.

 

---

 

Another example:

import { Equal, Expect } from '../helpers/type-utils';

interface User {
  id: string;
}

export class SDK {
  loggedInUser?: User;

  constructor(loggedInUser?: User) {
    this.loggedInUser = loggedInUser;
  }

  // How do we type this assertion function?
  assertIsLoggedIn(): asserts this is this & { loggedInUser: User } {
    if (!this.loggedInUser) {
      throw new Error('Not logged in');
    }
  }

  createPost(title: string, body: string) {
    type test1 = Expect<Equal<typeof this.loggedInUser, User | undefined>>;

    this.assertIsLoggedIn();

    type test2 = Expect<Equal<typeof this.loggedInUser, User>>;
  }
}

 

posted @ 2023-02-10 21:03  Zhentiw  阅读(12)  评论(0编辑  收藏  举报