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

proxyWithComputed does not recognize computed type if derived from another computed in typescript #217

Closed
homiebtc opened this issue Aug 18, 2021 · 3 comments

Comments

@homiebtc
Copy link

Hello,

When using proxyWithComputed in typescript, the type is not recognized when one computed value is derived from another computed value. Here is the example I was using:

// if you want a computed value to derive from another computed, you must declare the dependency first:
const state = proxyWithComputed({
  count: 1,
}, {
  doubled: snap => snap.count * 2,
  quadrupled: snap => snap.doubled * 2
})

Here is the example code sandbox https://codesandbox.io/s/sharp-driscoll-ddnzs?file=/src/App.tsx. It does not recognize the type for snap.doubled.

I see that the docs recommend react users to use derive, but I was not sure how to create a computed value that was derived from another computed value using derive. Please let me know what the proper way to do this for react and typescript.

Thanks!

@dai-shi
Copy link
Member

dai-shi commented Aug 18, 2021

When using proxyWithComputed in typescript, the type is not recognized when one computed value is derived from another computed value.

Please see #192. I will add a note in readme.

I was not sure how to create a computed value that was derived from another computed value using derive.

You can do something like this.
https://codesandbox.io/s/dawn-snow-zyk8t?file=/src/App.tsx

const state1 = proxy({ count: 0 });
const state2 = derive(
  {
    doubled: (get) => get(state1).count * 2
  },
  { proxy: state1 }
);
const state3 = derive(
  {
    quadrupled: (get) => get(state2).doubled * 2
  },
  { proxy: state2 }
);
// state1, state2 and state3 are all same object
console.log(state1 === state2);
console.log(state1 === state3);

Having separate state1, state2, and state3 are just for types.

In JavaScript, it can be just state.

const state = proxy({ count: 0 })
derive({ doubled: (get) => get(state).count * 2 }, { proxy: state })
derive({ quadrupled: (get) => get(state).doubled * 2 }, { proxy: state })

It may make sense not to override the existing proxy. In this case, types just work.

const state = proxy({ count: 0 })
const derived1 = derive({ doubled: (get) => get(state).count * 2 })
const derived2 = derive({ quadrupled: (get) => get(derived1).doubled * 2 })

@homiebtc
Copy link
Author

Ah I see, thanks so much!

dai-shi added a commit that referenced this issue Aug 18, 2021
@naivefun
Copy link

naivefun commented Nov 18, 2021

a workaround could be:

import { proxy } from 'valtio'
import { derive } from 'valtio/utils'

const rawState = proxy({ count: 1 })
const addOn1 = derive(
  {
    doubled: (get) => get(rawState).count * 2,
  },
  { proxy: rawState }
)
const addOn2 = derive(
  {
    quadrupled: (get) => get(addOn1).doubled * 2,
  },
  { proxy: addOn1 }
)

// here is the trick
type State = typeof rawState & typeof addOn1 & typeof addOn2
export const state = rawState as State

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

No branches or pull requests

3 participants