2016-04-15 194 views
0

TL; DR;我下面formatAPI功能是非常重载函数的打字稿方式...在TypeScript中使用不同参数类型覆盖函数的正确方法

我有可能被称为JavaScript的以下四个方面的两个函数:

jsf.format("format", function(){ return ... }); // string, function 

jsf.format("format"); // string 

jsf.format({ 
    "format1": function(){ return ... }, 
    "format2": function(){ return ... } 
}); // map[string:function] 

jsf.format(); // no params 

每签名在下面执行不同的逻辑。当然,我有以下几点:

function formatAPI(name: string, callback?: Function): any { 
    if (callback) { 
    registry.register(name, callback); 
    } else if (typeof name === 'object') { 
    registry.registerMany(name); 
    } else if (name) { 
    return registry.get(name); 
    } else { 
    return registry.list(); 
    } 
} 

但它不一致 - 例如,第二个参数是string。当我将其更改为string|Object时,它的逻辑失败(registry.register(name, callback); - name这里必须是字符串,而string|Object不能分配给字符串)。我试图找到一个清晰和可扩展的解决方案(为了能够在未来需要时添加更多的变体),我尝试去适应another question,但是我失败了。

我将不胜感激帮助和/或建议如何声明所有可能的签名为这个功能和函数体。

回答

3

它切片!它骰子!它使烤面包!

// Signatures 
function formatAPI(): string[]; 
function formatAPI(name: string): string; 
function formatAPI(name: string, callback: (arg: string) => void): void; 
function formatAPI(map: { [name: string]:() => string }): void; 
// Implementation 
function formatAPI(nameOrMap?: string | { [name: string]:() => string }, callback?:(arg: string) => void): string | string[] | void { 
    if (typeof nameOrMap === 'string') { 
    if (callback) { 
     return registry.register(nameOrMap, callback); 
    } else { 
     return registry.get(nameOrMap); 
    } 
    } else if (...) { 
    // Keep adding checks here 
    } 
} 

需要注意的一件事是编译器不使用签名来推断类型警卫的行为。这意味着你应该更谨慎地构建你的代码 - 在这里,我将string个案都放在typeof检查中。

+0

很好的答案!那么请你解释一下,如果编译器不使用类型警卫,那么编译器会如何使用这些签名? PS我可以看到TS编译器大量使用'ifof(typeof nameOrMap ==='string'){':)感谢'typeof'它知道他所在的类型上下文。 – ducin

+0

这些签名定义了调用合法的东西带有的函数,以及使用特定类型的集合调用时返回的内容 –