英文:
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",
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论