Yomguithereal / baobab

JavaScript & TypeScript persistent and optionally immutable data tree with cursors.
MIT License
3.15k stars 115 forks source link

Integration with flowtype #487

Open ThomasCrevoisier opened 7 years ago

ThomasCrevoisier commented 7 years ago

It would be really nice to be able to have static type checking with Flow while using baobab.

I didn't push Flow that far though, so I don't know if it's possible at the moment. I could give a try if you are interested :)

Yomguithereal commented 7 years ago

I don't know Flow enough to do this myself but I am sure it is possible for a library to come with some kind of flow definition files for external consomption with flow.

Yomguithereal commented 7 years ago

I could give a try if you are interested :)

Don't hesitate to do so. Just know that I probably won't be able to know if what you did is good :).

volgar1x commented 6 years ago

@ThomasCrevoisier did you make any progress on this issue ?

ThomasCrevoisier commented 6 years ago

Sorry about giving no news... I looked at it and I don't think the lib is well-suited for a typechecker as we access properties dynamically via strings. Of course we can mimic TypeScript interfaces, but using any everywhere is not satisfying IMHO. That's why I didn't push this further, but we can reproduce what has been done on TypeScript interfaces if it's needed :)

radekmie commented 6 years ago

I've prepared a basic typing, enough for my needs. If anyone would test and/or finish it, I'd polish it and make a PR for flow-typed.

declare class Baobab extends events$EventEmitter {
  apply(updater: (any) => any): any;
  clone(): any;
  concat(path: BaobabPath, value: any[]): any;
  deepClone(): any;
  // deepMerge()
  exists(path: BaobabPath): boolean;
  get(path: BaobabPath): any;
  merge(path: BaobabPath, value: any): any;
  // pop
  // project
  push(path: BaobabPath, value: any): any;
  // serialize
  set(path: BaobabPath, value: any): any;
  // shift
  // splice
  unset(path: BaobabPath): void;
  // unshift
  // update()

  static dynamicNode: (
    ...definition: (BaobabPath | ((...paths: any[]) => any))[]
  ) => BaobabMonkeyDefinition;
  static monkey: (
    ...definition: (BaobabPath | ((...paths: any[]) => any))[]
  ) => BaobabMonkeyDefinition;

  commit(): Baobab;
  constructor(initialData?: {}, options?: BaobabOptions): void;
  getMonkey(path: BaobabPath): null | BaobabMonkey;
  release(): void;
  select(): BaobabCursor;
  select(path: BaobabPath): BaobabCursor;
  toJSON(): any;
  toString(): string;
  validate(affectedPaths?: string[][]): boolean;
  watch(mapping: {[string]: BaobabPath}): BaobabWatcher;
}

declare class BaobabCursor extends events$EventEmitter {}

declare class BaobabMonkey {}

declare class BaobabMonkeyDefinition {}

declare type BaobabOptions = {
  asynchronous?: boolean,
  autoCommit?: boolean,
  immutable?: boolean,
  persistent?: boolean,
  pure?: boolean,
  validate?: (prevState: {}, nextState: {}, affectedPaths: string[][]) => void,
  validationBehavior?: 'notify' | 'rollback'
};

declare type BaobabPath = (number | string | {[string]: number | string})[];

declare class BaobabWatcher extends events$EventEmitter {
  get(): any;
  getCursors(): {[string]: BaobabCursor};
  getWatchedPaths(): string[][];
  refresh(mapping: {[string]: BaobabPath}): void;
  release(): void;
}

declare module 'baobab' {
  declare module.exports: typeof Baobab;
}