正在检测意外属性



我经常使用对象来传递一组选项。

在99.9%的情况下,我希望这些对象只包含我使用的属性的子集。如果出现意外属性,则意味着几乎总是存在拼写错误或逻辑错误。

有没有一种简单的方法可以确保选项对象不包含意外的属性?我只会在测试和调试期间真正需要它,所以它不一定要高效。

示例:

function log( text, opts={} ) {
const {times=1, silent=false, logger=console} = opts

if (silent) return

for (let i=0; i<times; i++) {
logger.log( text )
}
}
// all good here
log( "Hello World!", {times:1} )
// "slient" is not a valid option. It's a typo.
// I want this call to throw an exception.
log( "Bye World!", {times:2, slient:true} )

我知道我可以通过一个接收预期属性名称的函数来实现它:

function testOpts( opts={}, optNames=[] ) { /* ... */ }
testOpts( opts, ["times", "silent", "logger"] )

但维护这一点很无聊,而且容易出错:每次更改选项时,我都需要更新这些参数。我试过了,但经常忘记更新,所以我的函数一直接受我删除的参数,这是我想避免的。

有没有更好的解决方案可以让我只写一次属性名称?

如果只想写一次,唯一的方法是在使用它们的log函数中。确实有一种方法可以做到这一点:在析构函数中使用rest语法,并测试除了预期的(析构函数(属性之外没有其他属性:

function log( text, opts={} ) {
const {times=1, silent=false, logger=console, ...rest} = opts
//                                                ^^^^^^^
assertEmpty(rest);

if (silent) return

for (let i=0; i<times; i++) {
logger.log( text )
}
}
function assertEmpty(val) {
const keys = Object.keys(val);
if (keys.length) {
throw new RangeError(`Unexpected properties ${keys.join(', ')} in object`);
}
}

除此之外,使用TypeScript或Flow等静态分析工具,他们会很容易发现这些错误。

最新更新