Skip to content
This repository has been archived by the owner on Feb 14, 2023. It is now read-only.

Typescript Support #10

Closed
Troepster opened this issue Nov 6, 2018 · 10 comments
Closed

Typescript Support #10

Troepster opened this issue Nov 6, 2018 · 10 comments
Assignees
Labels
documentation The documentation should be improved. feature A new feature is requested. help wanted The owner cannot resolve this on their own.
Milestone

Comments

@Troepster
Copy link

Hi, not really an issue but rather a feature request: loving Reactn, I've started using it in my projects, any plans to make it typescript ready?

@quisido quisido added the feature A new feature is requested. label Nov 6, 2018
@quisido
Copy link
Collaborator

quisido commented Nov 6, 2018

I would love to support TypeScript. It was an intention before, and I'm not sure what stopped me. I think the build process wouldn't have translated so well at the time, but I don't think that is a problem anymore.

I imagine currently it may be easier to throw in a .d.ts file than to convert what exists to TypeScript, but I am not opposed to either method. :)

@quisido quisido added help wanted The owner cannot resolve this on their own. documentation The documentation should be improved. labels Nov 6, 2018
@quisido quisido self-assigned this Nov 6, 2018
@Troepster
Copy link
Author

I was thinking the same, a .d.ts would be a great start, if I get a working one ready I will fork and send a pull request, bit swamped currently but will try and contribute in the near future :)

@quisido
Copy link
Collaborator

quisido commented Nov 6, 2018

I tried a complete TS rewrite, and it did not go over so well. Namely because of all the class components that extend from React's Component/PureComponent. There are different implementations depending on if you use a decorator, extend, or HOC. The generics simply went over my head.

I've come up with this so far for a straight .d.ts file, but have not had time to test it thoroughly:

/// <reference types="typescript" />

import ReactN, {
  Component as ReactComponent,
  ComponentType,
  PureComponent as ReactPureComponent,
  ReactElement
} from 'react';

interface AnyObject {
  [key: string]: any;
}

type GlobalCallback = (global: GlobalState) => void;

// TypeScript does not allow props P to be passed to static methods.
declare class GlobalComponent<P = {}, S = {}> extends ReactComponent<P, S> {
  static getDerivedGlobalFromProps?: (props: AnyObject, prevGloba: GlobalState, prevState: AnyObject) => NewGlobal;
  private _globalCallback: () => void;
  readonly global: Readonly<GlobalState>;
  setGlobal(newGlobal: NewGlobal, callback?: GlobalCallback): Promise<void> | void;
}

declare class GlobalPureComponent<P = {}, S = {}> extends ReactPureComponent<P, S> {
  static getDerivedGlobalFromProps?: (props: AnyObject, prevGloba: GlobalState, prevState: AnyObject) => NewGlobal;
  private _globalCallback: () => void;
  readonly global: Readonly<GlobalState>;
  setGlobal(newGlobal: NewGlobal, callback?: GlobalCallback): Promise<void> | void;
}

type GlobalReducer = (state: GlobalState, ...args: any[]) => NewGlobal;

type GlobalPropertySetter = (value: any) => void;

interface GlobalState {
  [key: string]: any;
}

type GlobalStateSetter = (newGlobal: NewGlobal, callback?: GlobalCallback) => Promise<void> | void;

type LocalReducer = (...args: any[]) => void;

type MapGlobalToProps<ComponentProps, NewProps> = (global: GlobalState, props: ComponentProps) => NewProps;

type NewGlobal = NewGlobalFunction | null | Partial<GlobalState> | Promise<NewGlobalFunction> | Promise<null> | Promise<Partial<GlobalState>>;

type NewGlobalFunction = (global: GlobalState) => NewGlobal;

interface ReactN {
  (Component: ComponentType): GlobalComponent;
  addReducer: (name: string, reducer: GlobalReducer) => void;
  Component: GlobalComponent;
  default: ReactN;
  PureComponent: GlobalPureComponent;
  setGlobal: (newGlobal: NewGlobal, callback?: GlobalCallback) => Promise<void> | void;
  useGlobal:
    (() => [ GlobalState, GlobalStateSetter ]) |
    (<Property extends keyof GlobalState>(property: Property, setterOnly?: boolean) => [ GlobalState[Property], GlobalPropertySetter ]) |
    ((reducer: GlobalReducer) => LocalReducer);
  withGlobal: <CP, NP>(getGlobal: MapGlobalToProps<CP, NP>) => (Component: ComponentType<CP & NP>) => GlobalPureComponent<CP, never>;
}

export = ReactN;

If you want to start with it and go from there, you're more than welcome. It is published in the typescript-d-ts branch.

I haven't tested it in an actual React TS app, but at least it's not throwing errors in itself.

I'll have to port a project over to TypeScript to test more, as I don't actually any any TS projects using ReactN at the moment.

@Troepster
Copy link
Author

I'll plop it in my code and test, thanks

@justinhandley
Copy link

I'm actively running a typescript project and just moved to reactn for global state tonight - I'm loving it and also having quite a few errors - I'll open separate issues for them, but will also contribute what I can to the type file.

@quisido
Copy link
Collaborator

quisido commented Nov 8, 2018

By errors you mean type errors with the above implementation? Contributions are greatly appreciated. :)

@quisido
Copy link
Collaborator

quisido commented Nov 19, 2018

Any luck on a working implementation @Troepster @justinhandley ?

I am very interested in getting TypeScript support working in production.

@Troepster
Copy link
Author

@CharlesStover cannot say I've made any progress, I've moved to Context for now in my current project, I will definitely try and get back to this lib soon, as I think you've got the core simplicity of things down.

@justinhandley
Copy link

Hi @CharlesStover - I also haven't gotten anywhere. I am still using your library as an HOC and have simply used 'declare module reactn' to get past all the failures. At one point I started trying to rewrite into Typescript, but that got a bit overwhelming - it would probably take me a couple of days to get through it all cleanly and effectively. This is still on my mind, I just don't know how fast it will happen.

@quisido
Copy link
Collaborator

quisido commented Nov 27, 2018

That's all alright. Thanks for the support! I've buckled down today to get this in a working state. It supports everything except the React properties (createElement, useEffect, useState, etc.). The React namespace works fine (React.MouseEvent), but the properties themselves just need to be imported from the base react package for TypeScript files for the time being. Though it works at runtime, I'm having trouble getting the TS linter to recognize that the properties exist on the ReactN object.
I'll most likely have this deployed within the hour.

@quisido quisido added this to the 0.1.2 milestone Nov 27, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
documentation The documentation should be improved. feature A new feature is requested. help wanted The owner cannot resolve this on their own.
Projects
None yet
Development

No branches or pull requests

3 participants