听起来您希望对象参数是可选的,并且对象中的每个属性也是可选的。在示例中,如提供的那样,不需要重载语法。我想在这里的一些答案中指出一些不好的做法。诚然,这不是本质上写的最小可能的表达box = { x: 0, y: 87, width: 4, height: 0 }
,但这提供了您可能希望从所描述的类中获得的所有代码提示细节。此示例允许您使用一个、一些、全部或没有参数调用函数,并且仍然获得默认值。
/** @class */
class Box {
public x?: number;
public y?: number;
public height?: number;
public width?: number;
constructor(params: Box = {} as Box) {
// Define the properties of the incoming `params` object here.
// Setting a default value with the `= 0` syntax is optional for each parameter
let {
x = 0,
y = 0,
height = 1,
width = 1
} = params;
// If needed, make the parameters publicly accessible
// on the class ex.: 'this.var = var'.
/** Use jsdoc comments here for inline ide auto-documentation */
this.x = x;
this.y = y;
this.height = height;
this.width = width;
}
}
需要添加方法吗? 一个冗长但更可扩展的替代方案:上面
的Box
类可以作为接口工作,因为它们是相同的。如果您选择修改上述类,您将需要为传入参数对象定义和引用一个新接口,因为Box
该类不再看起来与传入参数完全相同。?:
注意在这种情况下,表示可选属性的问号 ( ) 移动的位置。由于我们在类中设置默认值,因此它们保证存在,但它们在传入参数对象中是可选的:
interface BoxParams {
x?: number;
// Add Parameters ...
}
class Box {
public x: number;
// Copy Parameters ...
constructor(params: BoxParams = {} as BoxParams) {
let { x = 0 } = params;
this.x = x;
}
doSomething = () => {
return this.x + this.x;
}
}
无论您选择哪种方式来定义您的类,这种技术都提供了类型安全的护栏,但可以灵活地编写以下任何一种:
const box1 = new Box();
const box2 = new Box({});
const box3 = new Box({x:0});
const box4 = new Box({x:0, height:10});
const box5 = new Box({x:0, y:87,width:4,height:0});
// Correctly reports error in TypeScript, and in js, box6.z is undefined
const box6 = new Box({z:0});
编译后,您会看到仅在未定义可选值时如何使用默认设置;var = isOptional || default;
它通过检查来避免广泛使用(但容易出错)的回退语法的缺陷void 0
,它是 的简写undefined
:
编译输出
var Box = (function () {
function Box(params) {
if (params === void 0) { params = {}; }
var _a = params.x, x = _a === void 0 ? 0 : _a, _b = params.y, y = _b === void 0 ? 0 : _b, _c = params.height, height = _c === void 0 ? 1 : _c, _d = params.width, width = _d === void 0 ? 1 : _d;
this.x = x;
this.y = y;
this.height = height;
this.width = width;
}
return Box;
}());
附录:设置默认值:错误的方式
(||
或)运算符
在设置默认后备值时考虑 /or 运算符的危险,||
如其他一些答案所示。下面的代码说明了设置默认值的错误方法。在针对0、''、null、undefined、false、NaN 等虚假值进行评估时,您可能会得到意想不到的结果:
var myDesiredValue = 0;
var result = myDesiredValue || 2;
// This test will correctly report a problem with this setup.
console.assert(myDesiredValue === result && result === 0, 'Result should equal myDesiredValue. ' + myDesiredValue + ' does not equal ' + result);
Object.assign(this,params)
在我的测试中,使用 es6/typescript 解构对象可以比 Object.assign 快 15-90%。使用解构参数仅允许您分配给对象的方法和属性。例如,考虑这种方法:
class BoxTest {
public x?: number = 1;
constructor(params: BoxTest = {} as BoxTest) {
Object.assign(this, params);
}
}
如果另一个用户没有使用 TypeScript 并试图放置一个不属于的参数,比如说,他们可能会尝试放置一个z
属性
var box = new BoxTest({x: 0, y: 87, width: 4, height: 0, z: 7});
// This test will correctly report an error with this setup. `z` was defined even though `z` is not an allowed property of params.
console.assert(typeof box.z === 'undefined')