Typescript 中的参数与选项

Argument vs options in Typescript

基于这个问题Multiple arguments vs. options object

我想知道这如何适用于 Typescript。我想做出这样的决定:

我现在发现的优缺点:

在我看来,这同样适用于 TypeScript。不要依赖 IDE 来提示您代码的作用。最好让代码告诉你它的作用。

参数越多,代码的可读性就越差

取下面的代码:

sendMsg("Poem", "I sing of brooks, of blossoms, birds and bowers.", new Date(2015, 9, 20));

我们或许可以看出第一个参数是标题,第二个参数是body,但是第三个参数有什么作用呢?这里的日期是什么意思?

我们要看函数签名才能看到:

function sendMsg(title: string, body: string, dateToSend = new Date())

所以现在我们知道第三个参数是什么了,但是即使我们使用的是 TypeScript,我们仍然需要做一些调查并查看函数签名。或者,我们可以将鼠标移到函数调用上,让我们的开发环境告诉我们,但这仍然不理想。

参数过多会使更改变得困难并增加出错的机会

现在假设我们想添加一个名为 dateToSendAgain 的新必需日期参数。我们的函数签名更改为:

function sendMsg(title: string, body: string, dateToSendAgain: Date, dateToSend = new Date())

这里有一个问题,我们原来的函数调用没有抛出编译错误,意思也变了:

// now creates a message with dateToSendAgain = new Date(2015, 9, 20)
// and dateToSend = new Date()
sendMsg("Poem", "I sing of brooks, of blossoms, birds and bowers.", new Date(2015, 9, 20));

尽管我们最初打算 dateToSend 成为 new Date(2015, 9, 20),但现在是 new Date(),也许我们不希望 dateToSend 成为 new Date(2015, 9, 20)

改用 object 属性

我们可以通过让我们的原始函数签名使用带有属性的 object 来解决所有这些问题(注意不需要接口):

function sendMsg(options: { title: string; body: string; dateToSend?: Date; dateToSendAgain: Date; }) {
    // we now have to define our default values here though...
    // if we use destructuring it's not too bad:
    const {title, dateToSend = new Date()} = options;
    // ...rest of function body omitted...
}

所以我们的原始代码应该是这样的:

sendMsg({
    title: "Poem", 
    body: "I sing of brooks, of blossoms, birds and bowers.", 
    dateToSend: new Date(2015, 9, 20)
});

...这很容易快速理解发生了什么。

此外,当我们去添加 dateToSendAgain 时,它会很容易,我们会得到一个编译错误,通知我们用新的 属性 更新我们所有的函数调用:

sendMsg({
    title: "Poem", 
    body: "I sing of brooks, of blossoms, birds and bowers.", 
    dateToSend: new Date(2015, 9, 20),
    dateToSendAgain: new Date(2015, 10, 20)
});

建议

我的建议是:

  1. 在参数不多的情况下使用多个参数,看函数名就可以理解每个参数的含义。
  2. 否则使用 object 属性。
  3. 如果可读性好,可以将这两者混合在一起。

Object 属性 文档

TypeScript uses JSDoc for code completion and so you can use this syntax for documenting properties of the object. Read here 关于如何记录它。

不幸的是,这似乎没有给我 Visual Studio 2013 中 TS 1.6 代码完成中的 object 属性的描述。

虽然使用界面似乎可行:

/**
 * The options for sendMsg
 */
interface SendMsgOptions {
    /**
    * The title of the message
    */
    title: string;
    // etc...
}

改变函数header:

function sendMsg(options: SendMsgOptions)

然后在使用的时候可以看到代码补全中的注释: