cssinjs / jss

JSS is an authoring tool for CSS which uses JavaScript as a host language.
https://cssinjs.org
MIT License
7.06k stars 397 forks source link

Research possibility to generate flow types from typescript #860

Open kof opened 5 years ago

kof commented 5 years ago

Thera are so many requests for typescript types and typescript seems to be a better alternative. What if we are able to generate flow types from typescript and cover both groups? I really hate dividing community on this.

https://github.com/joarwilk/flowgen

HenriBeck commented 5 years ago

So you are thinking about rewriting everything?

kof commented 5 years ago

Only if ot gives us a way to support both type systems from one code base

On Wed, Sep 19, 2018, 21:06 Henri notifications@github.com wrote:

So you are thinking about rewriting everything?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/cssinjs/jss/issues/860#issuecomment-422922424, or mute the thread https://github.com/notifications/unsubscribe-auth/AADOWLqQwxhWqfggnL7zVcgOrTR56h2-ks5ucpWkgaJpZM4Wv-tN .

HenriBeck commented 5 years ago

Isn't there a way of generating typescript types from flow?

kof commented 5 years ago

I assumed its not possible, because I imagined all the weak typing and magic, but evtl it is possible if typing is fully covered manually just found one project https://github.com/bcherny/flow-to-typescript

HenriBeck commented 5 years ago

@kof https://github.com/joarwilk/flowgen this doesn't convert typescript source files to flow definitions. It only converts typescript definition files, which means it would be useless in our case.

LaurensBosscher commented 5 years ago

We have semi-working Flow types:

// @flow

declare module "react-jss" {
    /*
    P = Props
    OP = OwnProps
    Def = DefaultProps
    St = StateType
  */

    declare type Null = null | void;

    declare type Dictionary = { [key: string]: {} };

    declare type StatelessComponent<P> = (props: P) => ?React$Element<any>;

    declare type ClassComponent<Def, P, St> = Class<React$Component<P, St>>;

    declare class ConnectedComponent<OP, P, Def, St> extends React$Component<
        OP,
        St
    > {
        static InnerComponent: Class<React$Component<P, St>>;
        static defaultProps: void;
        props: OP;
        state: St;
    }

    declare type ConnectedComponentClass<OP, P, Def, St> = Class<
        ConnectedComponent<OP, P, Def, St>
    >;

    declare type Connector<OP, P> = {
        (
            component: StatelessComponent<P>
        ): ConnectedComponentClass<OP, P, void, void>,
        <Def, St>(
            component: ClassComponent<Def, P, St>
        ): ConnectedComponentClass<OP, P, Def, St>,
        (component: Null): ConnectedComponentClass<OP, P, void, void>
    };

    declare export type Classes<Styles> = {
        [classname: $Keys<Styles>]: string
    };

    declare export type Sheet<Styles> = {
        attached: boolean,
        classes: Classes<Styles>,
        deployed: boolean,
        linked: boolean,
        options: Object,
        renderer: mixed,
        rules: mixed
    };

    declare type InjectedProps<Styles> = {
        classes: Classes<Styles>,
        sheet: Sheet<Styles>,
        theme?: Dictionary
    };

    declare type Theme = Dictionary | ((parentTheme: Theme) => Dictionary);

    declare type StylesCreatorFn<S> = (theme: Theme) => S;

    declare export default function injectStyle(
        styles: ?Object
    ): <Props, Component: React$ComponentType<Props>>(
        WrappedComponent: Component
        // return class because of https://github.com/facebook/flow/issues/6057
    ) => Class<
        React$Component<
            $Diff<React$ElementConfig<Component>, { classes: any | void }>
        >
    >;

    // TODO: improve `JssProvider` type
    declare export class JssProviderType extends React$Component<any, any> {}

    // TODO: improve `ThemeProvider` type
    declare export class ThemeProvider extends React$Component<any, any> {}

    declare export function withTheme<ThemeType, OP>(
        component: StatelessComponent<$Supertype<{ theme: ThemeType } & OP>>
    ): ConnectedComponentClass<
        OP,
        $Supertype<{ theme: ThemeType } & OP>,
        void,
        void
    >;

    declare export function withTheme<ThemeType, OP, Def, St>(
        component: ClassComponent<
            Def,
            $Supertype<{ theme: ThemeType } & OP>,
            St
        >
    ): ConnectedComponentClass<
        OP,
        $Supertype<{ theme: ThemeType } & OP>,
        Def,
        St
    >;

    declare export function createTheming(
        customChannel: string
    ): {
        channel: string,
        withTheme: Function,
        ThemeProvider: ThemeProvider,
        themeListener: {}
    };
}

These were created from a bunch of different PRs in Flow-typed. Getting them accepted in Flow-typed proved to be a bit of a challenge and we haven't had time for this. I think apart from the JssProviderType and ThemeProvider these should be usable for everyone

With a bit of work, I could probably type JssProviderType and ThemeProvider but this has not proved necessary for us so far.

Let me know if you would be interested in this!

I've also checked if we could generate flow-types from the TS type definitions that have been committed by @HenriBeck. That almost seems to work:

laurensbosscher@MBP-van-Laurens:~/dev/flow-gen$ npx flowgen types.d.ts
Parsing types
Missing node parse ExportDeclaration
"NO PRINT IMPLEMENTED: TypeOperator"
"NO PRINT IMPLEMENTED: MappedType"

The resulting definition is:

/**
 * Flowtype definitions for types
 * Generated by Flowgen from a Typescript Definition
 * Flowgen v1.2.3
 * Author: [Joar Wilk](http://twitter.com/joarwilk)
 * Repo: http://github.com/joarwilk/flowgen
 */

declare export var jss: Jss;
declare export var createGenerateId: CreateGenerateId;
declare export var JssProvider: React.ComponentType<{
  jss?: Jss,
  registry?: SheetsRegistry,
  generateId?: GenerateId,
  classNamePrefix?: string,
  disableStylesGeneration?: boolean,
  children: React.ReactNode
}>;
declare type Omit<T, K> = Pick<
  T,
  Exclude<"NO PRINT IMPLEMENTED: TypeOperator", K>
>;
declare type Options = {
  index?: number,
  inject?: Array<"classes" | "theme" | "sheet">,
  jss?: Jss
} & StyleSheetFactoryOptions;
declare type InjectedProps<Styles, Theme> = {
  classes: "NO PRINT IMPLEMENTED: MappedType",
  theme?: Theme,
  sheet?: StyleSheet
};
declare export default function injectSheet<Style, Theme, Props>(
  styles: Style,
  options?: Options
): (
  comp: React.ComponentType<Props>
) => React.ComponentType<Omit<Props, InjectedProps<Styles, Theme>>>;

So perhaps we can use this to implement the JssProviderType and ThemeProvider but it doesn't seem to be possible to generate them automatically from the TS definitions as part of the build.

sammi commented 5 years ago

i guess porting the whole lib to typescript might be a good solution

kof commented 5 years ago

I am still not sure if we can generate all flow types we need.

TrySound commented 5 years ago

Шило на мыло. I would prefer to rewrite everything in reason.

LaurensBosscher commented 5 years ago

I am still not sure if we can generate all flow types we need.

We can't.

We can, however, use them to speed up the process significantly. Would it perhaps be possible to talk this through over chat with the rest of the team (or the people interested in this :) )?.

I'm willing to put in the work to create a PR for this but I need to know first in which direction this project would like to proceed.

kof commented 5 years ago

@LaurensBosscher the ideal case would be to use one of them directly in code and generate typings for the other one, but we need good typings otherwise its better to do it manually and this is where I am not sure, I don't know if we can do everything we need with compiler from ts. Someone needs to start and see.

sammi commented 5 years ago

we can exprt js module from ts by babel, so same code base for both

LaurensBosscher commented 5 years ago

@kof ,

I totally agree that would be great!

I've tried running a few files through flowgen (which seems to be the most mature solution at the moment) and I've already run into a few limitations. I do hope someone is able to get it working but to me, it seems that doing it manually is the best way forward.

HenriBeck commented 5 years ago

@LaurensBosscher jss v10 will add flow and TS types for all of our packages.