Reputation: 9708
Got this weird situation. Building for react native and using a native package from Intercom. Importing it works fine when android or ios. But for the web (or node jest) it throws an error. So have to do some face-pattern "hacking" like this
utilities/Intercom/index.ios.ts
export { default } from '@intercom/intercom-react-native'
utilities/Intercom/index.web.ts
export default function Intercom() {}
some file that uses Intercom
// @ts-ignore
import Intercom from '~/utilities/Intercom' // Cannot find module '~/utilities/Intercom' or its corresponding type declarations.ts(2307)
...
Intercom.logout() // no TS support
Not only does TS complain, but I also loses all types ðŸ˜
Is there any other way to do platform specific import and keep the native types?
The error in jest (node) is Cannot read property 'UNREAD_CHANGE_NOTIFICATION' of undefined
which is also described in their docs. Problem is that I can't mock it out when using react-native-web that comes with expo.
Upvotes: 4
Views: 1648
Reputation: 20835
I think this is what you're looking for https://stackoverflow.com/a/43531355/1868008
In your utilities
directory, create a file named Intercom.d.ts
and there place the following
import DefaultIos from "./Intercom/index.ios";
import * as ios from "./Intercom/index.ios";
import DefaultWeb from "./Intercom/index.web";
import * as web from "./Intercom/index.web";
declare var _test: typeof ios;
declare var _test: typeof web;
declare var _testDefault: typeof DefaultIos;
declare var _testDefault: typeof DefaultWeb;
export * from "./Intercom/index.ios";
export default DefaultIos;
Not sure what all those are. Maybe something used in typescript internals.
And for the tests, it seems you'll need to mock every method you use in the code you're testing, e.g., in this App component; I'm using the logEvent
method, so I return it in the mock object of the library
import React from "react";
import renderer from "react-test-renderer";
import App from "./App";
jest.mock("@intercom/intercom-react-native", () => ({ logEvent: jest.fn() }));
describe("<App />", () => {
it("has 1 child", () => {
const tree = renderer.create(<App />).toJSON();
expect(tree.children.length).toBe(1);
});
});
App.tsx
...
import Intercom from "./utilities/Intercom";
export default function App() {
Intercom.logEvent("test", {});
...
}
For the web implementation, you could import the type to ensure compliance with the library interface
import type { IntercomType } from "@intercom/intercom-react-native";
const webImplementation: IntercomType = {
// here implement all methods
};
export default webImplementation;
https://github.com/diedu89/expo-isomorphic-import-ts
Upvotes: 2