【问题标题】:Exporting newable function from TypeScript declaration file从 TypeScript 声明文件中导出 newable 函数
【发布时间】:2021-09-28 00:43:14
【问题描述】:

我正在尝试为具有 newable 函数的库添加类型,但发现它真的很难做到。

简单地说:

export default function Api<T>(opts?: Settings): Api<T>;

我得到 “只有一个 void 函数可以用 'new' 关键字调用”。我知道new 关键字在声明文件中有效,例如:

export default interface Api {
    new<T=any>(opts?: Settings): Api<T>
}

这只是导出一个类型,正如编译器所说:“仅引用一个类型,但在这里用作值”

我不能在这里使用类,因为 API 可以通过其他文件的插件进行扩展,并且类型声明合并不适用于类(我希望其他文件添加的方法能够也可以由他们自己的打字文件打字)。

我不知所措 - 有什么想法吗?

【问题讨论】:

  • 图书馆在 npm 上是偶然的吗?
  • @Hcaertnit 它适用于 DataTables.net,但我需要更改类型以允许它现在可以以两种不同的方式初始化。有一个newable 函数可以工作,或者一个可以添加方法的类。后者似乎不可能,前者我不知道如何使它工作。

标签: typescript


【解决方案1】:

我无法得到与您完全相同的错误,但我能够在 TypeScript 4.3.5 中将一些东西拼凑在一起,使您的默认导出成为一个(可增强的)接口,您仍然可以定期调用并用作构造函数:

api.d.ts

interface Settings {
    setting?: string;
}

declare interface Api<T> {
    getValue(): T;
    <T>(opts?: Settings): Api<T>;
    new<T>(opts?: Settings): Api<T>;
}

declare const Api: Api<any>;

export default Api;

index.ts

import Api from './api';

// Augmentation the interface
declare module './api' {
    export default interface Api<T> {
        newField: number;
    }
}

// Test the default export as Api instance
Api.getValue();
console.log(Api.newField);

// See if we can call/new the Api instance
const api = new Api<number>();
const api2 = Api<number>();
const api3: Api<number> = null!;

// Test the created instance as Api instance
const value: number = api.getValue();
console.log(api.newField);

Api值的类型是Api&lt;any&gt;,而api/api2/api3的类型都是Api&lt;number&gt;。我们可以在所有这些上使用.getValue(),也可以使用例如增强它。 .newField 属性,然后我们可以从所有这些属性中读取。

基本上,因为declare interface 只创建了一个类型,所以我添加了一个declare const 来创建导出的实际值。类似于declare class 将类实例的接口和实际类作为值导出。我使用了两个 declares 后跟一个 export default,因为 TS 不允许您导出两个默认值,即使一个是纯粹的类型而另一个是纯粹的值。

【讨论】:

  • 有趣的解决方案。看起来有点像here 上的建议:)
  • @Braks 我猜你的意思是this specific answer 吗?它确实让我想起了 TypeScript 的内置类型 interface Objectvar Object: ObjectConstructor。不是我有意识地想到的,但确实很像。
  • 没错。我喜欢您的解决方案,尽管它完成了工作,可读且不使用 hacky 东西:D
  • @KelvinSchoofs 太棒了!这正是我想要的——谢谢!
猜你喜欢
  • 2018-10-27
  • 2020-09-13
  • 2021-04-14
  • 2012-12-31
  • 1970-01-01
  • 1970-01-01
  • 2020-11-22
  • 2018-09-23
  • 2017-01-26
相关资源
最近更新 更多