打字稿:从实现中发出具有不同类型的声明文件?

Typescript: emit declarations file with different types from implementation?

是否可以指示 TypeScript 编译器发出与实现中使用的类型不同的声明文件?例如:

// source brewery.ts
function brewBeer(name: unknown): Beer { ... }

// emitted brewery.d.ts
declare function brewBeer(name: string): Beer;

“你为什么要那个?”

我正在用 TypeScript 编写一个库,我希望它也可以用于非 TypeScript 项目。出于这个原因,我在 运行 时间检查传递给公开函数的参数的有效性,如下所示:

export function brewBeer(name: string): Beer {
  if (typeof name !== 'string') {
    throw new TypeError(`'${name}' is not a beer name.`);
  }
  // Continue brewing...
}

这种方法可用但不完美:

  1. 当传递了不正确类型的参数时,我无法对行为进行单元测试,因为测试文件也在 TypeScript 中,当不满足类型约束时,测试甚至不会 运行:

    TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.

  2. 编译器当然不会在编译时强制验证参数。

乍一看,这两个问题都可以用 unknown top 类型解决:

  1. 我可以在我的测试中传递任何类型的参数来评估运行时间行为。
  2. 编译器通过在使用它们之前强制断言函数参数来提供帮助。

然而,这种方法也有缺陷,因为发出的声明如下所示:

// brewery.d.ts
declare function brewBeer(name: unknown): Beer;

这在使用 TypeScript 的项目中几乎没有用处。

那么,有没有一种方法可以使用 unknown 并仍然发出具有 "correct" 类型的声明文件而无需手动更正它们?

Is it possible to instruct the TypeScript compiler to emit declaration files with different typings than the ones used in implementation.

简单的回答:没有。

I cannot unit test the behavior when incorrect type of parameters are passed

在您的测试中使用 any 转换或 // @ts-ignore:

brewBeer(42 as any);
// @ts-ignore
brewBeer(42);

由于 @ts-ignore 影响整行(因此您可能会拼错 brewBeer),我更喜欢 any 方法。