可以告诉闭包编译器两个类型定义相交吗?

huangapple go评论52阅读模式
英文:

Is it possible to tell closure compiler that 2 typedef intersect?

问题

Sure, here's the translated code without the code comments:

/**
 * @typedef {Object} Params
 * @property {string} attribute1
 * @property {string} attribute2
 * @property {string} attribute3
 */

/**
 * @typedef {Object} Options
 * @property {string | undefined} attribute1
 * @property {string | undefined} attribute2
 * @property {string | undefined} attribute3
 */

class Model {
    /**
     * @param {Options=} options
     */
    constructor(options = {}) {
        /** @private {Params} */
        this.params = { ...this.getDefaults(), ...options };
    }

    /**
     * @return {Params}
     */
    getDefaults() {
        return {
            attribute1: "default value 1",
            attribute2: "default value 2",
            attribute3: "default value 3",
        };
    }
}

/* Create a custom model by overriding only one attribute */
const model = new Model({
    attribute2: "custom value",
});

Note: I've removed the HTML escape codes around the string values for better readability.

英文:

I have a class for a model that contains a configuration, a plain object, with default values, and I want to create instances of this class by overriding only some of the configuration keys by passing another plain object, the options. I also want the code to work properly after being compiled in advanced mode and the keys of the configuration and options renamed.

/**
 * @typedef {{
 *     attribute1: string,
 *     attribute2: string,
 *     attribute3: string
 * }}
 */
let Params;

/**
 * @typedef {{
 *     attribute1: (string|undefined),
 *     attribute2: (string|undefined),
 *     attribute3: (string|undefined)
 * }}
 */
let Options;

class Model
{
    /**
     * @param {!Options=} options
     */
    constructor(options = {})
    {
        /** @private {!Params} */
        this.params = /** @type {!Params} */(Object.assign(this.getDefaults(), options));
    }

    /**
     * @return {!Params}
     */
    getDefaults()
    {
        return {
            attribute1: "default value 1",
            attribute2: "default value 2",
            attribute3: "default value 3",
        };
    }
}

/* Create a custom model by overriding only one attribute */
const model = new Model({
    attribute2: "custom value",
});

My problem is I don't know how to tell the compiler that types "Params" and "Options" shoud keep the same keys.
In advanced mode the properties will be renamed to something different.
For example Params.attribute1 will become Params.a and Options.attribute1 will become Options.b so I cannot merge them anymore.
Is there a way to make sure that the renamed properties still match ?

答案1

得分: 1

OK,我找到了一个可行的解决方案。
似乎@record是一种特殊类型,会自动与任何其他类型相交。
使用下面的解决方案,类型检查可以正常工作,并且可以重命名属性而不会破坏任何内容。

/** @record */
const Params = function() {};
/** @type {string} */Params.prototype.attribute1;
/** @type {string} */Params.prototype.attribute2;
/** @type {string} */Params.prototype.attribute3;

/** @record */
const Options = function() {};
/** @type {(string|undefined)} */Options.prototype.attribute1;
/** @type {(string|undefined)} */Options.prototype.attribute2;
/** @type {(string|undefined)} */Options.prototype.attribute3;

class Model
{
    /**
     * @param {!Options=} options
     */
    constructor(options = {})
    {
        /** @private {!Params} */
        this.params = /** @type {!Params} */(Object.assign(this.getDefaults(), options));
    }

    /**
     * @return {!Params}
     */
    getDefaults()
    {
        return {
            attribute1: "默认值1",
            attribute2: "默认值2",
            attribute3: "默认值3",
        };
    }
}

/* 通过仅覆盖一个属性来创建自定义模型 */
const model = new Model({
    attribute2: "自定义值",
});
英文:

OK I found a working solution.
Seems like @record is a special type that automatically intersect any other type it can.
With the solution below type checking works and properties are renamed without breaking anything.

/** @record */
const Params = function() {};
/** @type {string} */Params.prototype.attribute1;
/** @type {string} */Params.prototype.attribute2;
/** @type {string} */Params.prototype.attribute3;

/** @record */
const Options = function() {};
/** @type {(string|undefined)} */Options.prototype.attribute1;
/** @type {(string|undefined)} */Options.prototype.attribute2;
/** @type {(string|undefined)} */Options.prototype.attribute3;

class Model
{
    /**
     * @param {!Options=} options
     */
    constructor(options = {})
    {
        /** @private {!Params} */
        this.params = /** @type {!Params} */(Object.assign(this.getDefaults(), options));
    }

    /**
     * @return {!Params}
     */
    getDefaults()
    {
        return {
            attribute1: "default value 1",
            attribute2: "default value 2",
            attribute3: "default value 3",
        };
    }
}

/* Create a custom model by overriding only one attribute */
const model = new Model({
    attribute2: "custom value",
});

huangapple
  • 本文由 发表于 2023年5月10日 22:55:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76219905.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定