Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support React Native Platform-specific extensions in TypeScript with Import Unions #46822

Open
5 tasks done
sverrejoh opened this issue Nov 16, 2021 · 1 comment
Open
5 tasks done
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript

Comments

@sverrejoh
Copy link
Member

sverrejoh commented Nov 16, 2021

Suggestion

🔍 Search Terms

react native platform forking

✅ Viability Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

Support React Native Platform-specific extensions in TypeScript by typing the
import as a type union of the available modules.

In React Native any module file can be replaced by a platform-specific
implementation. For example a UserProfileImage.tsx module can have additional
implementations such as UserProfileImage.windows.tsx ,
UserProfileImage.macos.tsx and UserProfileImage.ios.tsx. React Native will
resolve to module with the most specificity, and each platform will bundle with
its own file.

This suggestion is to add support in TypeScript to support platform-specific
extensions in such a way that importing a forked module will type it as
a Union Type combining the type of each of the forked modules.

The react native resolution would be enabled as a typescript configuration, together
with a list of platforms to support.

📃 Motivating Example

Say we have the following file modules:

  • UserProfileImage.tsx
  • UserProfileImage.windows.tsx
  • UserProfileImage.macos.tsx
  • UserProfileImage.android.tsx

Which is imported as follows:

import UserProfileImage from "./UserProfileImage"

Because UserProfile is a forked module, the resulting UserProfile type will
not be the base module (or any of the forks), but a union type of all of
them. Essentially, with tokens matching the filename the type will be as follows:

type UserProfileModule =
    | typeof UserProfileImage
    | typeof UserProfileImageWindows
    | typeof UserProfileImageIOS        
    | typeof UserProfileImageAndroid;

This will provide type safety for the imported module, and ensure that the code
works in all the represented platforms.

💻 Use Cases

This will be useful for any React Native project using Platform-specific extensions. Currently the easiest way to solve this is to fork TypeScript and modify the module resolution to handle the platforms as a set of file extensions and run TypeScript once per platform, with different parameters.

@RyanCavanaugh RyanCavanaugh added Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript labels Nov 16, 2021
@tadhgmister
Copy link

How are you managing your props interfaces? If you have one common interface for which props are expected which is reused by each implementation then there is absolutely nothing gained by this since every member of that union would behave identically.

And inserting in extra properties to that common interface with declare module is really easy:

// can do this in each specific sub module to insert new properties to the components props
declare module './comp' {
  interface Props {
    iosSpecificProp?: string;
  }
}

working implementation Do you get anything else by having a union of all implementations other than automatically detecting prop types? I feel like managing props in any way other than a single interface seems like a recipe for disaster, and given how easy it is to insert extra properties from the implementation specific modules I don't see any reason to do it any other way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

3 participants