简体   繁体   中英

How to declare the type of a setter in JavaScript/VSCode/TypeScript?

I have a very simple example, to demonstrate the issue:

class Person {
    _name = '';
    _age  = 0;
    get name() {
        return this._name;
    }
    /**
     * @type {string}
     */
    set name(name) {
        this._name = name;
    }
    get age() {
        return this._age;
    }
    /**
     * @type {number | string}
     */
    set age(age) {
        if (age === 'too old') {
            age = 100000;
        }
        this._age = age;
    }
}

I use VSCode to do typechecking, but why does it fail on the type?

I explicitly say that the age setter can take either a number or a string:

在此处输入图像描述

You didn't define the type but instead wrote a JSDoc comment. That doesn't actually affect your code. Thus TypeScript implicitly sets the type number .

If you want the setter to accept both string and number one solution would be to use a union type like this:

set age(age: string | number) {
   ...
}

Keep in mind that you get problems when setting this._age later on because this._age also implicitly has the type number (default value 0 ) and therefore cannot be assigned a value of type string | number string | number .

I believe you need to wrap your union types in parenthesise to be valid in JSDoc:

/**
* @type {(number | string)}
*/

From the documentation :

Multiple types (type union) This can be a number or a boolean.{(number|boolean)} This means a value can have one of several types, with the entire list of types enclosed in parentheses and separated by |.

The following snippet should work. Just check the type of age with typeof to narrow the type into an if statement.

class Person {
  _name = '';
  _age  = 0;
  get name() {
      return this._name;
  }
  /**
   * @param {string} name
   */
  set name(name) {
      this._name = name;
  }
  get age() {
      return this._age;
  }
  /**
   * @param {number | string} age
   */
  set age(age) {
      if (typeof age === 'string') {
        if (age === 'too old') {
          age = 100000;
        } else {
          age = parseInt(age)
        }
      }
      this._age = age;
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM