Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixes for TS types and added types to unit tests #937

Merged
merged 17 commits into from
Jul 25, 2018
Merged

fixes for TS types and added types to unit tests #937

merged 17 commits into from
Jul 25, 2018

Conversation

xaviergonz
Copy link
Contributor

@xaviergonz xaviergonz commented Jul 20, 2018

A (kinda big) pull request to fix lots of TS typing issues
Oh, and also added types to all tests

As a plus I publicly exported TestFlags so mst-middlewares won't complain that it can't find them.

A couple of important things:

  • I made frozen T part of C,S,T deeply immutable (deep immutable array for arrays, deep immutable map for maps, deep immutable object for objects and nothing for already immutable primitives, all in a recursive manner)
  • Made arrays and maps optional (as per docs)
  • Made frozen(default) optional, while frozen() is not
  • Frozen doesn't automatically add "| undefined" as valid creation type, the user has to actually provide it.
  • Lots of other fixes actually.

Fixes: #923 #930 #932 - maybe #922

Btw, shouldn't custom type actually use <C, S, T> rather than <S|T,S,T> for more flexibility?

@xaviergonz
Copy link
Contributor Author

xaviergonz commented Jul 20, 2018

There's one unit test failing now that wasn't failing before adding TypeFlags to exports):

  • it should emit snapshots for children
    but weirdly enough it also fails now when I run the tests over the master branch...
 it should emit snapshots for children

    expect(received).toEqual(expected)

    Expected value to equal:
      {"files": [{"name": "01-arrival"}, {"name": "Photo2"}], "name": "Vacation photos"}
    Received:
      {"name": "01-arrival"}

    Difference:

    - Expected
    + Received

      Object {
    -   "files": Array [
    -     Object {
        "name": "01-arrival",
    -     },
    -     Object {
    -       "name": "Photo2",
    -     },
    -   ],
    -   "name": "Vacation photos",
      }

      139 |     onSnapshot(folder.files[0], snapshot => snapshots.push(snapshot))
      140 |     folder.files[0].rename("01-arrival")
    > 141 |     expect(snapshots[1]).toEqual({
          |                          ^
      142 |         name: "Vacation photos",
      143 |         files: [{ name: "01-arrival" }, { name: "Photo2" }]
      144 |     })

@xaviergonz
Copy link
Contributor Author

Apparently the error was an accidental change to mobx-state-tree package-json that changed mobx version to 4.3.1 from 5.0.3.
I restored it and now everything seems to be fine.

@xaviergonz
Copy link
Contributor Author

besides making TypeFlags public and exported also added TypeFlags imports to undo-manager and the other mst-middleware to fix #930

@mobxjs mobxjs deleted a comment from xaviergonz Jul 20, 2018
@xaviergonz
Copy link
Contributor Author

Also fixes #932

@xaviergonz
Copy link
Contributor Author

just added a fix (with unit test) for optional enums inside a model crashing
in other words, the following will crash:

test("should support optional enums inside a model", () => {
    const TrafficLight = types.model({
        color: types.optional(types.enumeration(["Red", "Orange", "Green"]), "Orange")
    })
    const l = TrafficLight.create({})
    expect(l.color).toBe("Orange")
})

because types.optional would inherit as flag TypeFlags.Union, but not "types" and therefore crash here

function tryGetOptional(type: any): OptionalValue<any, any, any> | undefined {
    if (!type) return undefined
    if (type.flags & TypeFlags.Union) return type.types.find(tryGetOptional) // THIS LINE
    if (type.flags & TypeFlags.Late) return tryGetOptional(type.subType)
    if (type.flags & TypeFlags.Optional) return type
    return undefined
}

so I fixed it like this

function tryGetOptional(type: any): OptionalValue<any, any, any> | undefined {
    if (!type) return undefined
    // we need to check for type.types since an optional union doesn't have direct subtypes
    if (type.flags & TypeFlags.Union && type.types) return type.types.find(tryGetOptional)
    if (type.flags & TypeFlags.Late && type.subType) return tryGetOptional(type.subType)
    if (type.flags & TypeFlags.Optional) return type
    return undefined
}

another option would be to make optional just return the optional flag, but I'm not sure if that's better

@mweststrate
Copy link
Member

mweststrate commented Jul 20, 2018 via email

@xaviergonz
Copy link
Contributor Author

Maybe fixes #922

@xaviergonz
Copy link
Contributor Author

xaviergonz commented Jul 22, 2018

Ok, basically I took the opportunity to make a revamp of the typescript typing to further improve it.
Notable changes is that ISnapshottable is no longer there and its role has been taken by IStateTreeNode<C=any,S=any>

With these changes now getSnapshot is properly typed without the need to use its generic argument, references and identifiers work properly and lots of other little fixes.

While there are some small breaking changes about typings, the core API is not changed at all.

@xaviergonz
Copy link
Contributor Author

I made this available in npm as @xaviergonz/mobx-state-tree @xaviergonz/mst-middlewares for anybody that might want to give it a try btw

@xaviergonz
Copy link
Contributor Author

I had to remove DeepImmutable. While cool (made snapshots from getSnapshot unmodifiable, etc) I have a large project that uses MST and it was getting out of ram errors while compiling because of it.

That being said, I'm quite happy with the current state of the typings 👍 so I don't think I'll make further changes.

@mweststrate
Copy link
Member

@xaviergonz Thanks for the awesome work! Will play a bit with and release

@mweststrate mweststrate merged commit 708eb5a into mobxjs:master Jul 25, 2018
@xaviergonz
Copy link
Contributor Author

@mweststrate my pleasure :)

@mweststrate
Copy link
Member

Took a close look and these are great improvements! Really awesome work. I've just send you a maintainers invite, that will simplify the workflow for any future contributions a lot, as you can directly push, branch etc on this repo :-)!

@dpnolte
Copy link

dpnolte commented Jul 26, 2018

@xaviergonz thanks this fixes my issue 👍
I hope this get published soon on npm.

@marvwhere
Copy link

cool thx - tried it out (v3.0.2)

looks like it's causing some problems with fork-ts-checker-webpack-plugin - "Starting type checking and linting service..." will never finish and creating a node instance with >100% cpu

went back to 2.2.0 (working)
updated to 3.0.0 (working)
updated to 3.0.1 (not working)

Typescript 2.9
tslint 5.11.0

@mweststrate
Copy link
Member

mweststrate commented Jul 26, 2018 via email

@xaviergonz
Copy link
Contributor Author

I have seen that happen from time to time when there are lots of compilation errors. Basically the default node memory of node processes is around 512mb and complex type checking takes lots of ram and then crash.

Things I'd try include:

  • run tsc by itself on the command line: npx tsc -p .
  • give it more ram if it dies because of out of ram: NODE_OPTIONS=--max-old-space-size=4096 && tsc -p .
  • make use of the speed up trick (interface instead of typeof)
type CreationType = typeof SomeModel.CreationType
type SnapshotType = typeof SomeModel.SnapshotType
type Type = typeof SomeModel.Type
export interface ISomeModelCreation extends CreationType {}
export interface ISomeModelSnapshot extends SnapshotType {}
export interface ISomeModel extends Type {}

then using ISomeModelCreation, ISomeModelSnapshot, ISomeModel

or I guess TS could get their act together and optimize that :)

@Bnaya
Copy link
Member

Bnaya commented Jul 26, 2018

import { types, getSnapshot } from "mobx-state-tree";

const Square = types
    .model(
        "Square",
        {
            width: types.number
        }
    )

const a = getSnapshot(Square)

I'm getting this error for the getSnapshot call
Type 'IModelType<ModelPropertiesDeclarationToProperties<{ width: ISimpleType<number>; }>, {}, ModelCrea...' has no properties in common with type 'IStateTreeNode<any, {}>'.

I'm probably missing something :)

@mweststrate
Copy link
Member

mweststrate commented Jul 26, 2018 via email

@Bnaya
Copy link
Member

Bnaya commented Jul 26, 2018 via email

@marvwhere
Copy link

@xaviergonz I tried around, but still not helping. The strange thing is that it is working with 3.0.0. I used that version to remove all lint errors which popped up through the breaking changes. then went back to 3.0.2 - still not working (i mean it is compiling, but the linter is not working)

I try to play around with it a little bit and try to find out which commit breaks it.

@xaviergonz
Copy link
Contributor Author

so the compiler works but the linter doesn't? what if you just run tslint stand alone?

@mweststrate
Copy link
Member

mweststrate commented Jul 27, 2018 via email

@marvwhere
Copy link

kind of yes =/

NODE_OPTIONS=--max-old-space-size=4096 && npx tsc -p . command

working fine in 3.0.0 and does nothing in 3.0.1

@xaviergonz xaviergonz deleted the ts-typing-fixes branch August 25, 2018 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

TS Error with types.optional in 3.0.0
5 participants