-
Notifications
You must be signed in to change notification settings - Fork 641
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
Improving Typescript usability? #1201
Comments
Do you know https://github.com/charto/classy-mst ? |
@ksjogo Thanks, yeah that was actually one of the first ways I tried using MST - IIRC it seemed to only help with the |
true :( There are some workarounds though: const Node = types.model({
x: 5, // as an example
me: types.maybe(types.late((): IAnyModelType => Node))
})
node.((me) as Instance<typeof Node>).x // x here will be number or with an extra view and an interface const Node = types.model({
x: 5, // as an example
me: types.maybe(types.late((): IAnyModelType => Node))
}).views(self => ({
get _me(): INode { return self._me }
}))
interface INode extends Instance<typeof Node> {}
node._me!.x // x here will be number
node._me!._me!.x // same None of them are pretty though and none of them help with the typing of the snapshots though
just use
You should be able if you use the interface trick (at least for returning, not sure above accepting) (see above)
I thought that was fixed from MST 3.8 (at least in vscode), which IDE?
true too :(
Yeah, it is a shame that typescript doesn't support typing return arguments from generator functions. Until they add support for that there's no way to fix that. It is always possible to use an async function and use runInAction after each await to cover any self mutations though (or use another sync action) instead of flows |
That being said (about recursive props) I was making some tests and I found a way to "kind of" make it work type Omit<T, K> = Pick<T, Exclude<keyof T, K>>
type RecurseMe<T, P extends keyof T> = Omit<T, P> & { [k in P]?: RecurseMe<T, P> }
type ModelWithRecursiveProps<IT extends IAnyType, P extends keyof SnapshotIn<IT>> = IType<
RecurseMe<SnapshotIn<IT>, P>,
RecurseMe<SnapshotOut<IT>, P>,
RecurseMe<Instance<IT>, P>
>
const M = types
.model({
x: types.number,
m: types.maybe(types.late((): IAnyType => M)),
})
.actions(self => ({
setX(v: typeof self.x) {
self.x = v
}
}))
const RecursiveM: ModelWithRecursiveProps<typeof M, "m"> = M
const m = RecursiveM.create({ x: 5, m: { x: 6, m: { x: 7 } } }) // snapshots are properly type checked
const n = m.m!.m!.x // number
const n1 = m.m!.setX(5) // action is there
const n2 = m.x // number too @mweststrate do you think such type helper ( |
@xaviergonz Thanks for sharing that. However I just want to point out that none of my real-world use cases are such simple cases of self-recursion, but usually involve multiple co-recursive structures - it's just that the self-recursive case is the simplest to illustrate as an example. I do use VSCode. You're probably right in it being fixed by now, this was something I remembered from last time I tried. Ah, I missed the Thanks for acknowledging the other issues! |
Thanks to you for pointing them out, however they are known and I don't think they can be fixed until TS changes something... (or somebody comes up with some idea) |
Well, what do you think about the codegen approach? |
This issue has been automatically marked as stale because it has not had recent activity in the last 10 days. It will be closed in 4 days if no further activity occurs. Thank you for your contributions. |
This issue has been automatically unmarked as stale. Please disregard previous warnings. |
what I'm doing for circular is const Node = types.model({
x: 5, // as an example
me: types.maybe(types.late((): IAnyModelType => Node))
}).views( self => ({
get node() {
return self.me as Instance<typeof Node>
}
})
Node.create({}).node // typed me :) |
What I'm doing for async is this:
Then I can make any action async, all I have to do is wrap any modifications to the store using
This is far easier for me than trying to deal with flow and generators which I could never make TS behave well with. |
Yep, should work fine. But note that middleware that supports / reasons
about asynchronous actions won't be able to process this pattern correctly.
(probably no problem in most code bases)
…On Fri, Sep 13, 2019 at 4:51 PM amorsillo ***@***.***> wrote:
What I'm doing for async is this:
runInAction(actionName: string, fn: () => any) {
log.info(`runInAction from ${actionName}`)
return Promise.resolve(fn())
},
Then I can make any action async, all I have to do is wrap any
modifications to the store in await self.runInAction("loggingName", () =>
{ self.foo = "bar" })
This is far easier for me than trying to deal with flow and generators
which I could never make TS behave well with.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1201?email_source=notifications&email_token=AAN4NBFULC2PF5GH4CEOENLQJOSIHA5CNFSM4G37FYOKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD6VIILI#issuecomment-531268653>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAN4NBHIIIIPA34XCPSZH33QJOSIHANCNFSM4G37FYOA>
.
|
issue moved to : coolsoftwaretyler/mst-middlewares#10 |
Hey folks - this is not actually being moved. It got caught up in the issue migration because it matches |
Is your feature request related to a problem? Please describe.
MST sounds awesome. However, I've tried a couple times to start using MST in my TS codebases, but invariably abandon due to Typescript issues (at least as far as I know, and I don't know much).
A few examples:
self.otherAction()
from an action (again, without casts sprinkled).There are also opportunities for improved typing, such as models defaulting to read-only types outside of actions.
Describe the solution you'd like
I understand that some of these are chalked up to Typescript's limitations, but IMO improved TS usability is a worthy target given TS's momentum. At least for this user, TS usability is the main immediate barrier to adoption.
A different approach from embedded type system is code generation. Various GraphQL tools use this approach, as a random example.
I know this doesn't solve everything, e.g. flow generators, but I imagine it would be a big step up.
Downsides include more frontend infrastructure needed to execute code generation.
Describe alternatives you've considered
Are you willing to (attempt) a PR?
You wouldn't want a change like this in my hands....
The text was updated successfully, but these errors were encountered: