扩展全局暴露的第三方模块 [英] Extending third party module that is globally exposed

查看:19
本文介绍了扩展全局暴露的第三方模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试向 Typescript 中的 Jest 添加自定义匹配器.这工作正常,但我无法让 Typescript 识别扩展的 Matchers.

I am trying to add a custom matcher to Jest in Typescript. This works fine, but I can't get Typescript to recognize the extended Matchers.

myMatcher.ts

myMatcher.ts

export default function myMatcher (this: jest.MatcherUtils, received: any, expected: any): { pass: boolean; message (): string; } {
  const pass = received === expected;
  return {
    pass: pass,
    message: () => `expected ${pass ? '!' : '='}==`,
  }
}

myMatcher.d.ts

myMatcher.d.ts

declare namespace jest {
  interface Matchers {
    myMatcher (expected: any): boolean;
  }
}

someTest.ts

someTest.ts

import myMatcher from './myMatcher';

expect.extend({
  myMatcher,
})

it('should work', () => {
  expect('str').myMatcher('str');
})

tsconfig.json

tsconfig.json

{
  "compilerOptions": {
    "outDir": "./dist/",
    "moduleResolution": "node",
    "module": "es6",
    "target": "es5",
    "lib": [
      "es7",
      "dom"
    ]
  },
  "types": [
    "jest"
  ],
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "dist",
    "doc",
    "**/__mocks__/*",
    "**/__tests__/*"
  ]
}

在 someTests.ts 中,我收到错误

In someTests.ts, I get the error

error TS2339: Property 'myMatcher' does not exist on type 'Matchers'

我已多次阅读 Microsoft 文档,但我不知道如何将命名空间与全局可用类型(未导出)合并.

I have read through the Microsoft documentation several times, but I can't figure out how to do the namespace merging with globally available types (not exported).

将它放入 jest 中的 index.d.ts 工作正常,但对于快速变化的代码库和多方扩展的类来说,这不是一个好的解决方案.

Putting it in the index.d.ts from jest works fine, but isn't a good solution for a rapidly changing codebase and classes being extended by multiple parties.

推荐答案

好的,这里有几个问题

当源文件(.ts.tsx)文件和声明文件(.d.ts)文件都是候选文件时对于模块解析,就像这里的情况一样,编译器将解析源文件.

When a source file (.ts or .tsx) file and a declaration file (.d.ts) file are both candidates for module resolution, as is the case here, the compiler will resolve the source file.

您可能有两个文件,因为您想导出一个值并修改全局对象 jest 的类型.但是,您不需要为此使用两个文件,因为 TypeScript 具有用于从模块内扩展全局范围的特定构造.也就是说,你只需要下面的.ts文件

You probably have two files because you want to export a value and also modify the type of the global object jest. However, you do not need two files for this as TypeScript has a specific construct for augmenting the global scope from within a module. That is to say, all you need is the following .ts file

myMatcher.ts

// use declare global within a module to introduce or augment a global declaration.
declare global {
  namespace jest {
    interface Matchers {
      myMatcher: typeof myMatcher;
    }
  }
}
export default function myMatcher<T>(this: jest.MatcherUtils, received: T, expected: T) {
  const pass = received === expected;
  return {
    pass,
    message: () => `expected ${pass ? '!' : '='}==`
  };
}

也就是说,如果您遇到这种情况,最好在同一个文件中执行全局变异和全局类型增强.鉴于此,我会考虑将其重写如下

That said, if you have such a situation, it is a good practice to perform the global mutation and the global type augmentation in the same file. Given that, I would consider rewriting it as follows

myMatcher.ts

// ensure this is parsed as a module.
export {};

declare global {
  namespace jest {
    interface Matchers {
      myMatcher: typeof myMatcher;
    }
  }
}
function myMatcher<T>(this: jest.MatcherUtils, received: T, expected: T) {
  const pass = received === expected;
  return {
    pass,
    message: () => `expected ${pass ? '!' : '='}==`
  };
}

expect.extend({
  myMatcher
});

someTest.ts

import './myMatcher';

it('should work', () => {
  expect('str').myMatcher('str');
});

这篇关于扩展全局暴露的第三方模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆