在JavaScript中,通常有一种可以多种方式调用的函数 - 例如少数位置参数或单个选项对象或两者的某种组合。
我一直试图弄清楚如何注释这个。
我试过的一种方法是将rest args注释为各种可能元组的联合:
type Arguments =
| [string]
| [number]
| [string, number]
;
const foo = (...args: Arguments) => {
let name: string;
let age: number;
// unpack args...
if (args.length > 1) {
name = args[0];
age = args[1];
} else if (typeof args[0] === 'string') {
name = args[0];
age = 0;
} else {
name = 'someone';
age = args[1];
}
console.log(`${name} is ${age}`);
};
// any of these call signatures should be OK:
foo('fred');
foo('fred', 30);
foo(30);
以上片段是人为的;我可能只是在这个例子中使用(...args: Array<string | number>)
,但是对于更复杂的签名(例如涉及可以单独或使用先前args的类型化选项对象),能够定义精确的有限集合是有用的。可能的呼号。
但上面没有打字。您可以在tryflow中看到一堆令人困惑的错误。
我也尝试将函数本身键入单独的整个函数defs的联合,但是didn't work:
type FooFunction =
| (string) => void
| (number) => void
| (string, number) => void
;
const foo: FooFunction = (...args) => {
let name: string;
let age: number;
// unpack args...
if (args.length > 1) {
name = args[0];
age = args[1];
} else if (typeof args[0] === 'string') {
name = args[0];
age = 0;
} else {
name = 'someone';
age = args[1];
}
console.log(`${name} is ${age}`);
};
// any of these call signatures should be OK:
foo('fred');
foo('fred', 30);
foo(30);
如何处理带有多个可能的呼叫签名的类型注释函数? (或者,多重签名被认为是Flow中的反模式,我根本不应该这样做 - 在这种情况下,与第三方库进行交互的推荐方法是什么?)
答案 0 :(得分:6)
答案 1 :(得分:1)
在你给出的三种可能的训练中,我已经找到了如何使用单个选项对象使其工作,但是因为你需要设置至少一个对象,你需要定义每种可能性。
像这样:
type Arguments =
{|
+name?: string,
+age?: number
|} |
{|
+name: string,
+age?: number
|} |
{|
+name?: string,
+age: number
|};
const foo = (args: Arguments) => {
let name: string = args.name ? args.name : 'someone';
let age: number = typeof args.age === 'number' && !isNaN(args.age) ? args.age : 0;
console.log(`${name} is ${age}`);
}
// any of these call signatures are OK:
foo({ name: 'fred' });
foo({ name: 'fred', age: 30 });
foo({ age: 30 });
// fails
foo({});