From dfd0263e672404c2dfc0bd32cbce80eaf8a2bebd Mon Sep 17 00:00:00 2001 From: Ryan Linton Date: Wed, 14 Jun 2023 12:53:24 -0600 Subject: [PATCH 1/3] Create Platform isPlatform props proposal --- proposals/0645-platform-is-platform-props.md | 82 ++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 proposals/0645-platform-is-platform-props.md diff --git a/proposals/0645-platform-is-platform-props.md b/proposals/0645-platform-is-platform-props.md new file mode 100644 index 00000000..3b649b7e --- /dev/null +++ b/proposals/0645-platform-is-platform-props.md @@ -0,0 +1,82 @@ +--- +title: Platform isPlatform props +author: + - Ryan Linton +date: 2023-06-14 +--- + +# RFC0645: Platform isPlatform props + +## Summary + +Add `isAndroid`, `isIOS`, and `isNative` to `Platform`. + +## Basic example + +```ts +if (Platform.isAndroid) { + // do some Android only stuff here +} +``` + +## Motivation + +Platform already defines `isPad`, `isTV`, and `isTesting`. In consulting and the companies I've worked at I've seen dozens (even hundreds) of apps, and nearly all backfill the missing ones `isAndroid` and `isIOS` with something along the lines of the following: + +```ts +const isAndroid = Platform.OS === "android"; +const isIOS = Platform.OS === "ios"; +``` + +`Platform` should provide these since so many devs want to express one-off platform checks this way. + +## Detailed design + +I did an initial implementation [here](https://github.com/facebook/react-native/pull/37870) but it has some drawbacks. As @NickGerleman [pointed out](https://github.com/facebook/react-native/pull/37870#pullrequestreview-1478897922) we don't want to maintain a centralized list of platforms. A better solution that keeps the platform definitions in their respective platforms is to update `Platform` to be a proxy object. + +```ts +const Platform = new Proxy( + { + __constants: null, + OS: "android", + isAndroid: true, + isNative: true, + // ... + }, + { + get(target, prop) { + if (prop in target) { + return target[prop]; + } + + if (prop.toString().startsWith("is")) { + return false; + } + + return Reflect.get(...arguments); + }, + } +); +``` + +## Drawbacks + +- This change doesn't really offer any new functionality over conditional logic using `Platform.OS`. It's just a different (albeit quite common) way of expressing the same thing. +- As @motiz88 [points out](https://github.com/facebook/react-native/pull/37870#issuecomment-1591225470) this breaks existing optimizations with Babel transforms that remove dead code based on `Platform.OS` conditionals. This proposal likely further complicates that by making `Platform` a proxy object. +- All other platforms would need to update their `Platform` implementations to match. + +## Alternatives + +Another potential solution that doesn't use proxy but reads similarly would be to add an `is` method (e.g. `Platform.is('android')` or `Platform.is('ios')`). This may or may not have advantages considering the Babel transforms. It is less similar to the common code that inspired this proposal though. + +## Adoption strategy + +This is not a breaking change but would be a new API offering the same existing functionality provided by checking against `Platform.OS`. Existing React Native developers would upgrade to latest and discover via docs and types. + +## How we teach this + +Per motivation, React Native developers are already doing this. This just moves the definition of `isAndroid` and `isIOS` up into React Native. + +## Unresolved questions + +- Where are the Babel transforms for removing platform specific code and how do they work? From e3dbaede0d709b17dc0c27608d26f03a3ea38517 Mon Sep 17 00:00:00 2001 From: Ryan Linton Date: Wed, 14 Jun 2023 12:59:55 -0600 Subject: [PATCH 2/3] Update title --- proposals/0645-platform-is-platform-props.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0645-platform-is-platform-props.md b/proposals/0645-platform-is-platform-props.md index 3b649b7e..93068cce 100644 --- a/proposals/0645-platform-is-platform-props.md +++ b/proposals/0645-platform-is-platform-props.md @@ -1,11 +1,11 @@ --- -title: Platform isPlatform props +title: Platform isAndroid, isIOS, and isNative properties author: - Ryan Linton date: 2023-06-14 --- -# RFC0645: Platform isPlatform props +# RFC0645: Platform isAndroid, isIOS, and isNative properties ## Summary From 384574b39a0a78a9506d6362fad2b489b09fd1af Mon Sep 17 00:00:00 2001 From: Ryan Linton Date: Wed, 14 Jun 2023 13:13:26 -0600 Subject: [PATCH 3/3] Renumber --- ...-is-platform-props.md => 0670-platform-is-platform-props.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename proposals/{0645-platform-is-platform-props.md => 0670-platform-is-platform-props.md} (97%) diff --git a/proposals/0645-platform-is-platform-props.md b/proposals/0670-platform-is-platform-props.md similarity index 97% rename from proposals/0645-platform-is-platform-props.md rename to proposals/0670-platform-is-platform-props.md index 93068cce..2fdcfb37 100644 --- a/proposals/0645-platform-is-platform-props.md +++ b/proposals/0670-platform-is-platform-props.md @@ -5,7 +5,7 @@ author: date: 2023-06-14 --- -# RFC0645: Platform isAndroid, isIOS, and isNative properties +# RFC0670: Platform isAndroid, isIOS, and isNative properties ## Summary