Typescript path mapping for React Native *.android.ts and *.ios.ts modules
Asked Answered
M

4

16

I'm using Typescript (version 2.2.1) in VSCode (version 1.10.2) for my React Native project and I'm trying to get the compiler to map *.android.ts and *.ios.ts paths by using the instructions at:

https://github.com/Microsoft/TypeScript-Handbook/blob/release-2.0/pages/Module%20Resolution.md#path-mapping

For example:

import ApplicationTabs from './ApplicationTabs';

should map to

import ApplicationTabs from './ApplicationTabs/index.ios';

with the following tsconfig.json settings

{
    "compilerOptions": {
        "paths": {
            "*": ["*", "*.ios", "*.android"]
        }
   }
}

but instead throws the compiler throws the error "[ts] cannot find module './ApplicationTabs'"

Does anyone know how I might get the compiler to map to *.android.ts and *.ios.ts paths correctly?

My tsconfig.json is:

{
    "compilerOptions": {
        "target": "es6",
        "module": "es6",
        "moduleResolution": "node",
        "jsx": "react",
        "outDir": "build",
        "rootDir": "src",
        "removeComments": true,
        "allowSyntheticDefaultImports": true,
        "noImplicitAny": true,
        "experimentalDecorators": true,
        "preserveConstEnums": true,
        "allowJs": true,
        "inlineSourceMap": true,
        "sourceRoot": "src",
        "baseUrl": ".",
        "paths": {
            "*": [
                "*",
                "*.ios",
                "*.android"
            ]
        }
    },
    "filesGlob": [
        "typings/**/*.d.ts",
        "src/**/*.ts",
        "src/**/*.tsx",
        "src/**/*.tsx"
    ],
    "exclude": [
        "index.android.js",
        "index.ios.js",
        "build",
        "node_modules"
    ],
    "compileOnSave": false
}

Thanks :-)

Monney answered 28/3, 2017 at 0:48 Comment(2)
Would you mind posting your solution if you've found one?Nationalize
Hi Bijou, I didn't find a solution to this. I've just started learning React Native so I decided just write in Javascript for now.Monney
K
4

Looks like you're running into the issue reported here: https://github.com/Microsoft/TypeScript/issues/8328

According to the issue (and what I've found in my own projects) path resolution doesn't work for relative paths, like what you're doing in your code above. You also don't get type-checking between your .android and .ios files, so I've been using the other approach discussed in the issue:

./ApplicationTabs.d.ts

// This file exists for two purposes:
// 1. Ensure that both ios and android files present identical types to importers.
// 2. Allow consumers to import the module as if typescript understood react-native suffixes.
import DefaultIos from './ApplicationTabs.ios';
import * as ios from './ApplicationTabs.ios';
import DefaultAndroid from './ApplicationTabs.android';
import * as android from './ApplicationTabs.android';

declare var _test: typeof ios;
declare var _test: typeof android;

declare var _testDefault: typeof DefaultIos;
declare var _testDefault: typeof DefaultAndroid;

export * from './ApplicationTabs.ios';
export default DefaultIos;
Koran answered 20/4, 2017 at 23:12 Comment(0)
G
0

Continuing the issue… I was working on the same problem, and the simple solution for me is to use:

import ApplicationTabs from './ApplicationTabs/index';

In tsconfig, you don't need any "paths" section.

  1. This makes the tscompiler find the module ./ApplicationTabs/index.ts (this file must exist). Because (from https://github.com/Microsoft/TypeScript-Handbook/blob/release-2.0/pages/Module%20Resolution.md#path-mapping): A relative import will be resolved relative to the importing file. So import { b } from "./moduleB" in source file /root/src/folder/A.ts would result in the following lookups:

    /root/src/folder/moduleB.ts
    /root/src/folder/moduleB.d.ts
    
  2. The react-native packager (Metro) will find ./ApplicationTabs``/index.android.ts or ./ApplicationTabs/index.ios.ts, because react-native works that way.

Gwenni answered 8/2, 2020 at 13:13 Comment(1)
but how do we structure this? Assuming moduleB in this case is ApplicationTabs, does the actual moduleB code go into ./ApplicationTabs/index.ts OR in ./ApplicationTabs/index.ios.ts and ./ApplicationTabs/index.android.ts? I'm confused. ThanksDalessio
P
0

Now (typescript >= 4.7) you can use moduleSuffixes. Documentation: https://www.typescriptlang.org/tsconfig/#moduleSuffixes

tsconfig.json:

{
    "compilerOptions": {
        "moduleSuffixes": [".android", ".ios", ""]
    }
}
Pulp answered 27/6 at 6:18 Comment(0)
A
-4

Recommendations here is to use path mapping support, see https://github.com/Microsoft/TypeScript-Handbook/blob/release-2.0/pages/Module%20Resolution.md#path-mapping

so your tsconfig.json should contain something like:

{
    "compilerOptions": {
        "paths": {
            "*": ["*", "*.ios", "*.android"]
        }
   }
}

this will tell the compiler when resolving an import to BigButton to look at:

BigButton.tsx

BigButton.ios.tsx

BigButton.androdid.tsx

Acquaintance answered 18/4, 2017 at 2:46 Comment(1)
It appears this was copied from github.com/Microsoft/TypeScript/issues/…. This only works for absolute imports, not relative ones, as the question asker is referring to.Radiophone

© 2022 - 2024 — McMap. All rights reserved.