扩展在全球范围内公开的第三方模块 [英] Extending third party module that is globally exposed

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

问题描述

我正在尝试向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.

推荐答案

好的,所以这里有一些问题

OK, so there are a few issues here

当源文件(.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 ? '!' : '='}==`
  };
}

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

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天全站免登陆