Migrating Universal Modules to TypeScript
- Change Import
- Testing
- Move native
dependenciestopeerDependencies - Add module scripts
- Generate a
tsconfig.jsonfile 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 testto 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-smsIn 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.tsextension. There are cases (expo-avfor example) where you should separate types into smaller files.