成员声明,可以是带参数的方法,也可以是属性



如何对既可以是属性(不带参数(又可以是方法(带参数(的成员进行建模?

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"));

相关内容

最新更新