如何对既可以是属性(不带参数(又可以是方法(带参数(的成员进行建模?
WSH Enivronment 属性可以在没有参数的情况下从 Javascript 调用:
var shell = new ActiveXObject('WScript.Shell');
var env = shell.Environment;
或者,作为带有参数的属性,从 Javascript 中看起来像一个方法调用:
var filteredEnv = shell.Environment('System');
这两种情况都返回 WshEnvironment 的实例,这是环境变量的集合。
但是,作为没有任何参数的方法调用时会引发错误:
var env2 = shell.Environment();
我可以将其建模为属性或带参数的方法,但不能同时建模:
declare interface WshShell {
// ...
// Error: Duplicate identifier
Environment: WshEnvironment;
Environment(Type: 'System' | 'User' | 'Process' | 'Volatile'): WshEnvironment;
// ...
}
操场
我可以键入WshEnvironment & {(Type: 'System' | 'User' | 'Process' | 'Volatile'): WshEnvironment}
; 然后编译以下内容:
let x: WshShell;
console.log(x.Environment.Count);
console.log(x.Environment('Process').Count);
操场
但是 Typescript 会在从 x.Environment
返回的对象上推断出一个调用签名来过滤值,而调用签名实际上返回一个以参数作为其变量名称的值:
let env = x.Environment;
// Typescript will type filteredEnv as WshEnvironment
// At runtime, filteredEnv will contain an empty string (unless there is an environment variable named 'Process')
let filteredEnv = env('Process');
您可以声明具有扩展WshEnvironment
的调用签名的接口
// Added for testing
declare interface WshEnvironment{
(name: 'OS'): string
}
declare interface WshEnvironmentWithInvoke extends WshEnvironment {
(Type: 'System' | 'User' | 'Proces' | 'Volatile'): WshEnvironment;
}
declare interface WshShell {
Environment: WshEnvironmentWithInvoke;
}
let shell: WshShell;
shell.Environment("System")("OS");
shell.Environment("OS");
编辑
上述解决方案确实允许进行这样的调用:
let env = x.Environment;
let filteredEnv = env('System');
不幸的是,没有办法在 Typescript 中正确键入它,基本上是一个属性,当它被分配出对象时会丢失一些属性(。我会优化常见场景,这里似乎是您指定参数的版本,主要是因为文档中的这一行:
如果未提供 strType,则 Environment 属性将根据操作系统返回不同的环境变量类型。
我会创建一个辅助函数来为强制转换提供一些上下文,而不是内联:
declare interface WshEnvironment{
(name: 'OS'): string
}
declare interface WshShell {
Environment (Type?: 'System' | 'User' | 'Proces' | 'Volatile'): WshEnvironment
}
function defaultEnvironment(shell: WshShell) :WshEnvironment {
return shell.Environment as any;
}
var shell: WshShell = new ActiveXObject('WScript.Shell');
var s = defaultEnvironment(shell);
WScript.Echo(s("OS"));
WScript.Echo(shell.Environment('System')("OS"));