metro icon indicating copy to clipboard operation
metro copied to clipboard

ESM TypeScript support in the metro-resolver

Open MaijaHeiskanen opened this issue 2 years ago • 4 comments

Do you want to request a feature or report a bug?

Feature

What is the current behavior?

metro-resolver cannot resolve TypeScript imports that are in ESM format, e.g. have .js file extension in the import. It only adds extensions listed in sourceExts at the path, but does not consider situations where the original file extensions needs to be replaced.

What is the expected behavior?

metro-resolver should try to resolve TypeScript imports that are in ESM format. metro-resolver should try out the different file-extensions as it currently does, but in addition try out the file extensions also after removing the original file extension of the import. Example:

import {thing} from './something.js

Currently metro-resolver by default tries to resolve this as ./something.js, ./something.js.native, ./something.js.android.js, ./something.js.ts, ./something.js.android.ts, ... etc.

It should also try to resolve it as following: Currently metro-resolver by default tries to resolve this as ./something, ./something.native, ./something.android.js, ./something.ts, ./something.android.ts, ... etc. For my use case it should try to replace .js with .ts and .tsx, but there might be other use cases too.

Please provide your exact Metro configuration and mention your Metro, node, yarn/npm version and operating system.

Metro version: 0.67.0 Metro-resolver version: 0.67.0 Node version: 16.18.0 Yarn version: 1.22.4 Windows 11 and MacOS

// metro.config.js
const path = require('path');
const {getDefaultConfig} = require('metro-config');

module.exports = (async () => {
    const {
        resolver: { sourceExts, assetExts }
    } = await getDefaultConfig();

    return {
        projectRoot: path.resolve(__dirname, '.'),
        // watchFolders: [path.resolve(__dirname, './node_modules')],
        watchFolders: [
            path.resolve(__dirname, '../../node_modules'),
            path.resolve(__dirname, '../../packages/package1'),
            path.resolve(__dirname, '../../packages/package2'),
            path.resolve(__dirname, '../../packages/package3')
        ],
        resolver: {
            assetExts: assetExts.filter((ext) => ext !== 'svg'),
            // https://github.com/facebook/metro/issues/1#issuecomment-453450709
            extraNodeModules: new Proxy(
                {},
                {
                    get: (target, name) => path.join(process.cwd(), `node_modules/${name}`)
                }
            ),
            sourceExts: [...sourceExts, 'svg']
        },
        transformer: {
            babelTransformerPath: require.resolve('react-native-svg-transformer'),
            // eslint-disable-next-line require-await
            getTransformOptions: async () => ({
                transform: {
                    experimentalImportSupport: false,
                    inlineRequires: false
                }
            })
        }
    };
})();

MaijaHeiskanen avatar Nov 01 '22 13:11 MaijaHeiskanen