Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript 扩展全局公开的第三方模块_Typescript_Jestjs - Fatal编程技术网

Typescript 扩展全局公开的第三方模块

Typescript 扩展全局公开的第三方模块,typescript,jestjs,Typescript,Jestjs,我正在尝试添加一个自定义匹配器来在Typescript中开玩笑。这很好,但我无法让Typescript识别扩展的匹配器 myMatcher.ts export default function myMatcher (this: jest.MatcherUtils, received: any, expected: any): { pass: boolean; message (): string; } { const pass = received === expected; retur

我正在尝试添加一个自定义匹配器来在Typescript中开玩笑。这很好,但我无法让Typescript识别扩展的
匹配器

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

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

import myMatcher from './myMatcher';

expect.extend({
  myMatcher,
})

it('should work', () => {
  expect('str').myMatcher('str');
})
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__/*"
  ]
}
在一些tests.ts中,我得到了错误

error TS2339: Property 'myMatcher' does not exist on type 'Matchers'
我已经阅读了很多次Microsoft文档,但我不知道如何将名称空间与全局可用类型合并(不导出)


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

好的,这里有一些问题

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

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

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 ? '!' : '='}==`
  };
}
// 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
});
import './myMatcher';

it('should work', () => {
  expect('str').myMatcher('str');
});
declare global {
    namespace jest {
        interface Matchers<R> {
            // add any of your custom matchers here
            toBeDivisibleBy: (argument: number) => {};
        }
    }
}

// this will extend the expect with a custom matcher
expect.extend({
    toBeDivisibleBy(received: number, argument: number) {
        const pass = received % argument === 0;
        if (pass) {
            return {
                message: () => `expected ${received} not to be divisible by ${argument}`,
                pass: true
            };
        } else {
            return {
                message: () => `expected ${received} to be divisible by ${argument}`,
                pass: false
            };
        }
    }
});
import "path/to/customMatchers";

test('even and odd numbers', () => {
   expect(100).toBeDivisibleBy(2);
   expect(101).not.toBeDivisibleBy(2);
});
一个简单的方法是:

customMatchers.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 ? '!' : '='}==`
  };
}
// 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
});
import './myMatcher';

it('should work', () => {
  expect('str').myMatcher('str');
});
declare global {
    namespace jest {
        interface Matchers<R> {
            // add any of your custom matchers here
            toBeDivisibleBy: (argument: number) => {};
        }
    }
}

// this will extend the expect with a custom matcher
expect.extend({
    toBeDivisibleBy(received: number, argument: number) {
        const pass = received % argument === 0;
        if (pass) {
            return {
                message: () => `expected ${received} not to be divisible by ${argument}`,
                pass: true
            };
        } else {
            return {
                message: () => `expected ${received} to be divisible by ${argument}`,
                pass: false
            };
        }
    }
});
import "path/to/customMatchers";

test('even and odd numbers', () => {
   expect(100).toBeDivisibleBy(2);
   expect(101).not.toBeDivisibleBy(2);
});

@AluanHaddad的答案几乎是正确的,没有几种类型。 这一个有效:

export {};

declare global {
  namespace jest {
    interface Matchers<R> {
      myMatcher: (received: string) => R;
    }
  }
}

function myMatcher<T>(this: jest.MatcherUtils, received: string, expected: string): jest.CustomMatcherResult {
  const pass = received === expected;
  return {
    pass,
    message: (): string => `expected ${received} to be ${expected}`,
  }
}

expect.extend({
  myMatcher,
});
export{};
宣布全球{
名称空间玩笑{
接口匹配器{
myMatcher:(接收到:字符串)=>R;
}
}
}
函数myMatcher(this:jest.MatcherUtils,received:string,expected:string):jest.CustomMatcherResult{
const pass=已接收===预期值;
返回{
通过,
消息:():string=>`预期${received}为${expected}`,
}
}
期待({
myMatcher,
});
关于一个真实的例子,请参见(并且测试实际上通过:)。

tsconfig.json
中向
类型添加
,为我解决了这个问题

// tsconfig.json

"types": [
      "node",
      "jest",
      "@types/testing-library__jest-dom"
    ],

也可以看到这个答案

在这里,我认为可以将类型声明从.ts文件移到组织的.d.ts文件中。实际上,.d.ts文件只是普通javascript的一个ts外观。在那里也有很好的普通进口货。有趣的是,如果我将declare语句放在someTest.ts文件中,我将丢失其余的Matchers声明信息。因此TS编译器必须对声明顺序做一些奇怪的事情,我将不得不进一步研究。@DylanStewart声明可以从
.TS
文件分解到
.d.TS
文件中,但前提是它们具有不同的模块说明符。例如
my module.ts
my module声明.d.ts
正常,但
my module.ts
my module.d.ts
不正常。
.tsx
文件也是如此。@AluanHaddad我对您提出的解决方案有意见。如果我使用declare-global方法,它会工作,但是如果我将declare-namespace-jest分解到一个单独的模块中,然后导入该模块,它似乎不会工作。这是一个截图。你有什么想法吗@具有顶级
导入
导出
的文件是一个模块。要影响模块中的全局声明空间,需要使用
declare global
。您的
custom matchers.ts
具有顶级
import
,这意味着它是一个模块,需要块
declare global
@Tony您的代码所做的是声明一个模块范围的命名空间,该命名空间与
jest
global没有任何关系。通过配置选项,jest可以在测试之前自动导入
customMathers.ts
文件一次