vitalets / react-native-extended-stylesheet

Extended StyleSheets for React Native
MIT License
2.93k stars 132 forks source link

[improvement][typings] - proper type resolution completion #170

Open FrederickEngelhardt opened 2 years ago

FrederickEngelhardt commented 2 years ago

Steps to Reproduce

Any stylesheet.create() object key click for type completion in vscode

Example

const containerStylesRaw = {
  basic: basicContainer,
  center: centerContainer,
}

const containerStyles = EStyleSheet.create(containerStylesRaw)

Expected Behavior

Expect to resolve the object and key location in the .ts file.

Actual Behavior

The typings resolve to the node_modules/react-native-extended-stylesheet/types/index.d.ts declaration file

declare namespace EStyleSheet {
    type AnyObject = {[key: string]: any};

Show the code

Possible temp fix is to have a basic object and then export the EStylesheet and coherce the type as a typeof the raw object.

Example:

const containerStylesRaw = {
  basic: basicContainer,
  center: centerContainer,
}

const containerStyles = EStyleSheet.create(
  containerStylesRaw,
) as typeof containerStylesRaw

I'm doing this as a workaround and it will resolve to the containerStylesRaw object.

Followup solution

Replace the create and child methods with the NamedStyles type used in Stylesheet.create.

Make only the return use the type join to avoid having type errors when combining View, Text style properties in a single .create()

diff --git a/node_modules/react-native-extended-stylesheet/types/index.d.ts b/node_modules/react-native-extended-stylesheet/types/index.d.ts
index 74d1762..683521f 100644
--- a/node_modules/react-native-extended-stylesheet/types/index.d.ts
+++ b/node_modules/react-native-extended-stylesheet/types/index.d.ts
@@ -10,18 +10,18 @@
  * Adding key augmention is tracked here: https://github.com/Microsoft/TypeScript/issues/12754
  */

-import {StyleSheet} from 'react-native';
+import {StyleSheet, ViewStyle, TextStyle, ImageStyle } from 'react-native';

 export = EStyleSheet;

 declare namespace EStyleSheet {
-    type AnyObject = {[key: string]: any};
+    type NamedStyles<T> = { [P in keyof T]: ViewStyle | TextStyle | ImageStyle };
     type Event = 'build';

-    export function create(styles: AnyObject): AnyObject;
-    export function build(rawGlobalVars?: AnyObject): void;
+    export function create<T extends NamedStyles<T> | NamedStyles<any>>(styles: T | NamedStyles<T>): T;
+    export function build<T>(rawGlobalVars?: NamedStyles<T> | Record<string, any>): void;
     export function value(expr: any, prop?: string): any;
-    export function child(styles: AnyObject, styleName: string, index: number, count: number): AnyObject;
+    export function child<T>(styles: NamedStyles<T>, styleName: string, index: number, count: number): NamedStyles<T>;
     export function subscribe(event: Event, listener: () => any): void;
     export function clearCache(): void;

Environment

FrederickEngelhardt commented 1 year ago

Okay if anyone wants this change without adding patch package you can use my github's tag with this change forked off master.

https://github.com/VirtualizeLLC/react-native-extended-stylesheet/releases/tag/0.12.1

Replace your react-native-extended-stylesheet with this github tag in package.json and run yarn

    "react-native-extended-stylesheet": "github:VirtualizeLLC/react-native-extended-stylesheet#0.12.1",

Noting that the mixin types will not pass the typesafety due to them being strings when numbers are expected in many areas.