如何在声明文件中将实例与命名空间合并?

3
我该如何创建一个.d.ts文件来表示以下JavaScript API?
- `Loader` 是一个未全局导出的类。 - `loader` 是全局导出的,是 `Loader` 的一个实例。 - `loader.Loader` 是 `Loader` 类本身。 - `Loader` 有一个静态方法 `create`,用于创建 `Loader` 的实例。
因此,实际上 `loader` 的行为类似于一个命名空间,其中包括类 `Loader`,但也是 `Loader` 的一个实例。以下代码无法正常工作,因为TypeScript不会将命名空间与值合并:
declare namespace loader {
    class Loader {
        id: number;
        name: string;
        load(url: string): any;

        static create(name: string, parent?: Loader): Loader;
    } 
}

// This doesn't work, because a namespace cannot be merged with a value:
declare const loader: loader.Loader;

使用JavaScript调用此API的方式如下所示:
// Call load() on the default Loader instance
loader.load('/foo/index'); 

// loader.Loader is a class, and loader is an instance of it
if(loader instanceof loader.Loader) {  
    console.log('Yes, loader is a Loader');
}

// Create a new Loader instance
var myLoader = loader.Loader.create('my-loader'); 

// Call load on this Loader instance
myLoader.load('/bar/something'); 

// myLoader is also an instance loader.Loader
if(myLoader instanceof loader.Loader) {  
    console.log('Yes, myLoader is a Loader');
}
1个回答

1
我不太明白当你说“Loader未被全局导出”和“loader已被全局导出”时的意思。一件事情可以从模块中导出并可用于在其他模块中导入,或者未被导出-不存在“全局导出”的概念。另一方面,一件事情可以被声明存在于全局命名空间中,就像全局变量一样,在没有显式导入任何内容的情况下在每个模块中都可用。
如果您想从模块中导出带有额外Loader属性的loader,则无需声明命名空间-您可以在声明loader实例时使用交集类型添加Loader属性:

loader.d.ts

declare class Loader {
    id: number;
    name: string;
    load(url: string): any;

    static create(name: string, parent?: Loader): Loader;
}


declare const loader: Loader & { Loader: typeof Loader };

export {loader};  // Loader is not exported

导入loader后,您所有的示例都可以编译,如下所示:

import {loader} from './loader';


// Call load() on the default Loader instance
loader.load('/foo/index');

// loader.Loader is a class, and loader is an instance of it
if(loader instanceof loader.Loader) {
    console.log('Yes, loader is a Loader');
}

// Create a new Loader instance
var myLoader = loader.Loader.create('my-loader');

// Call load on this Loader instance
myLoader.load('/bar/something');

// myLoader is also an instance loader.Loader
if(myLoader instanceof loader.Loader) {
    console.log('Yes, myLoader is a Loader');
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接