Typescript 中的参数与选项
Argument vs options in Typescript
基于这个问题Multiple arguments vs. options object
我想知道这如何适用于 Typescript。我想做出这样的决定:
- 预编译器/lint 给出的提示将尽可能相关。
- generated documentation也会尽量干净
我现在发现的优缺点:
Typescript 可以很好地处理可选参数,但是依赖参数的顺序和长长的参数列表我觉得不太方便。
使用 option
对象很好,但需要为每个对象创建一个接口(?),据我所知,这会使代码过载,我不知道哪个然后将生成某种文档/提示。
在我看来,这同样适用于 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)
});
建议
我的建议是:
- 在参数不多的情况下使用多个参数,看函数名就可以理解每个参数的含义。
- 否则使用 object 属性。
- 如果可读性好,可以将这两者混合在一起。
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)
然后在使用的时候可以看到代码补全中的注释:
基于这个问题Multiple arguments vs. options object
我想知道这如何适用于 Typescript。我想做出这样的决定:
- 预编译器/lint 给出的提示将尽可能相关。
- generated documentation也会尽量干净
我现在发现的优缺点:
Typescript 可以很好地处理可选参数,但是依赖参数的顺序和长长的参数列表我觉得不太方便。
使用
option
对象很好,但需要为每个对象创建一个接口(?),据我所知,这会使代码过载,我不知道哪个然后将生成某种文档/提示。
在我看来,这同样适用于 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)
});
建议
我的建议是:
- 在参数不多的情况下使用多个参数,看函数名就可以理解每个参数的含义。
- 否则使用 object 属性。
- 如果可读性好,可以将这两者混合在一起。
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)
然后在使用的时候可以看到代码补全中的注释: