Migrating Universal Modules to TypeScript
- Change Import
- Testing
- Move native
dependencies
topeerDependencies
- Add module scripts
- Generate a
tsconfig.json
file withexpo-module-scripts
- Various Other Changes
To optimize our libraries for dead code elimination we should migrate our exports to be imported as such:
- import { FileSystem } from 'expo-file-system';
+ import * as FileSystem from 'expo-file-system';
Ideally we would make the main entry-point of a module be a file named like the module like build/FileSystem.js
package.json
- "main": "index.js",
+ "main": "build/<MODULE NAME>.js",
+ "types": "build/<MODULE NAME>.d.ts",
To migrate from libraries using different imports, we should add a deprecation notice.
A lot of libraries are just import from Expo, in these cases we can just the deprecation. Ensure you change all imports across
packages/
,apps/
, anddocs/
.
src/index.ts
import * as FileSystem from './FileSystem';
export * from './FileSystem';
let wasImportWarningShown = false;
// @ts-ignore: Temporarily define an export named "FileSystem" for legacy compatibility
Object.defineProperty(exports, 'FileSystem', {
get() {
if (!wasImportWarningShown) {
console.warn(
`The syntax "import { FileSystem } from 'expo-file-system'" is deprecated. Use "import * as FileSystem from 'expo-file-system'" or import named exports instead. Support for the old syntax will be removed in SDK 34.`
);
wasImportWarningShown = true;
}
return FileSystem;
},
});
Then eventually remove the index in favor of the named file. (src/FileSystem.ts
)
Migration should include the addition of a src/__tests__
which can be run with yarn test
in the root directory of the package.
- If the package is using the old structure of
test/
for utilities, they should migrate to usingjest-expo
.
src/__tests__/<MODULE NAME>-test.ts
- import { mockPlatformWeb } from '../../test/mocking';
+ import { mockPlatformWeb } from 'jest-expo';
- Add a jest object to the
package.json
package.json
"jest": {
"preset": "expo-module-scripts"
},
- Run
yarn test
to run the tests.
In the root .circleci/config.yaml
add a step to the job named expo_sdk
. This should be in alphabetic order with the other testing steps.
.circleci/config.yaml
- yarn:
command: test --maxWorkers 1
working_directory: ~/expo/packages/expo-sms
In order to prevent overlapping native code in node_modules
, we should move any dependencies
containing native code to peerDependencies
.
package.json
"scripts": {
"build": "expo-module build",
"clean": "expo-module clean",
"test": "expo-module test",
"prepare": "expo-module prepare",
"prepublishOnly": "expo-module prepublishOnly",
"expo-module": "expo-module"
}
To get the tsconfig
that we use in all of our modules, run expo-module prepare
or the yarn script yarn prepare
(given the script is defined in a module's package.json
)
/tsconfig.json
// @generated by expo-module-scripts
{
"extends": "expo-module-scripts/tsconfig.base",
"compilerOptions": {
"outDir": "./build"
},
"include": ["./src"],
"exclude": ["**/__mocks__/*", "**/__tests__/*"]
}
- Remove
babel-preset-expo
- Remove
flow
- For reusing types across the web implementation's native layer and API layer, types should be moved to a named file with the
.types.ts
extension. There are cases (expo-av
for example) where you should separate types into smaller files.