Home > Enterprise >  Type information for a conditional property in JSDoc
Type information for a conditional property in JSDoc

Time:09-07

I'm adding type information for TypeScript to an existing JavaScript library via JSDoc. I have a constructor function that might set a property based on the value(s) of the parameter(s) it's given:


/**
 * Settings you can use to configure an instance of an {@link ExampleClass}
 *
 * @typedef {Object} ExampleOptions
 * @property {true} [option] You can set this to `true` to make a property on an instance of {@link ExampleClass} exist. If you don't set it, that property won't exist
 */

/**
 * A thing that does stuff
 * 
 * @constructor
 * @param {ExampleOptions} [param] Options you can use to configure the new instance
 */
function ExampleClass(param) {
    if(param.option === true) {
        /**
         * A property that only exists based on the options given to this constructor
         *
         * @type {boolean}
         */
        this.property = true;
    }
}

I was hoping that TypeScript would externally interpret the declaration of property to be like property?: boolean;, but it looks like it gets interpreted to be non-optional, and comes up in the autocomplete in my editor without having to check for its existence ahead of time. Ideally, I'd like for it to be an optional property that you'd have to check for before you can use it, or even allow you to use it unchecked if TypeScript can somehow guarantee that you had passed {option: true} to the constructor. How can I make that work?

CodePudding user response:

Can you not just do

interface options {
   option? : boolean;
}

/**
 * A thing that does stuff
 * 
 * @constructor
 * @param {options} [param] Options you can use to configure the new instance
 */
function ExampleClass(param : options) {
    if(param.option === true) {
        /**
         * A property that only exists based on the options given to this constructor
         *
         * @type {boolean}
         */
        this.property = true;
    }
}

CodePudding user response:

Pre-declare the class with a @typedef with the optional properties and set it to the constructor as a variable of type {new () => ExampleClass}. This way it's even possible to declare this as the defined class and have code completion inside the constructor function itself. Something like the below:

/**
 * Settings you can use to configure an instance of an {@link ExampleClass}
 *
 * @typedef {Object} ExampleOptions
 * @property {true} [option] You can set this to `true` to make a property on an instance of {@link ExampleClass} exist. If you don't set it, that property won't exist
 */

/**
 * @typedef {object} ExampleClass
 * @prop {boolean} [property] A property that only exists based on the options given to this constructor
 */

/**
 * A thing that does stuff
 *
 * @constructor
 * @param {ExampleOptions} [param] Options you can use to configure the new instance
 * @this {ExampleClass}
 * @type {{new () => ExampleClass}}
 */
const ExampleClass = function (param) {
    if(param.option === true) {
        this.property = true;
    }
}

Screenshot

  • Related