My use case: I have a monorepo project, but it's not setup like workspaces. There's api, app, all unrelated, except the common project.

Common project just contains zod typings that are same on api and app, and I linked them via tsconfig.json

{
  "extends": "expo/tsconfig.base",
  "compilerOptions": {
    "strict": false,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "baseUrl": ".",
    "paths": {
      "@/*": [
        "./*"
      ],
      "@common": ["../common/index.ts"], // maybe just line below
      "@common/*": ["../common/*"],
    },
  },
  "include": [
    "**/*.ts",
    "**/*.tsx",
    "node_modules/**/*.ts",
    ".expo/types/**/*.ts",
    "expo-env.d.ts",
    "typings.d.ts"
  ],
  "exclude": [
    "node_modules/**/*.test.ts"
  ]
}

And my common project did not contain anything special: No package.json, no tsconfig.json, just ts modules.

And my metro bundler config is something like:

const projectRoot = __dirname;
const monorepoRoot = path.resolve(projectRoot, '..');

const { assetExts, sourceExts } = sentryConfig.resolver;
const monorepoPackages = {
  '@common': path.resolve(monorepoRoot, 'common'),
};
const extendedConfig = {
  projectRoot,
  watchFolders: [projectRoot, ...Object.values(monorepoPackages)],
  resolver: {
    unstable_enablePackageExports: false,
    nodeModulesPaths: [
      path.resolve(projectRoot, 'node_modules'), 
      path.resolve(monorepoRoot, 'node_modules')
    ],
    extraNodeModules: {
      ...monorepoPackages
    },
  },
};

It works for android and ios, but for web I just get a:

Cannot destructure property '__extends' of '_tslib.default' as it is undefined

Btw, my bundler for web is also metro. I needed to alias tslib to the proper build.

And how you do aliases in metro bundler is:

const ALIASES = {
  'tslib': require.resolve('tslib/tslib.es6.js'),
};
const extendedConfig = {
  resolver: {
    resolveRequest: (context, moduleName, platform) => {
      return context.resolveRequest(
        context,
        ALIASES[moduleName] ?? moduleName,
        platform
      );
    },
  }
}

I don't know why it wasn't properly aliased for web, but this solution applies to any kind of alias you'd need to manually adjust. More info about available options in metro bundler docs.