-
-
Notifications
You must be signed in to change notification settings - Fork 256
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
refactor(types): make Snapshot<T>
use read-only collections
#850
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit fa5d99f:
|
Map and Set are not read-only, so it's not correct. |
@dai-shi, sorry for not making myself clear enough. i'm not actually using const store = proxy({ set: proxySet() })
const snap = snapshot(store)
snap.set.add("!") // TypeError: ... object is not extensible this is the type of case that should be reflected by the typings. i think the main issue lies in the fact that i think that there are only two solutions:
|
Thanks for the clarification. Branding might work, but we don't want to complicate our implementation. Our suggestion is module augmentation. Lines 56 to 64 in 26caa88
Define your declare module 'valtio' {
function useSnapshot<T extends object>(p: T): MySnapshot<T>
} Do you know if it's possible to augment types when users import |
yeah, it seems that just putting the augmentation in |
Nice. |
On second thought, I'm not sure if it's narrowing, but I'm probably okay with this: diff --git a/src/vanilla.ts b/src/vanilla.ts
index aceafef..26c4fcd 100644
--- a/src/vanilla.ts
+++ b/src/vanilla.ts
@@ -5,8 +5,6 @@ const isObject = (x: unknown): x is object =>
type AnyFunction = (...args: any[]) => any
-type AsRef = { $$valtioRef: true }
-
type ProxyObject = object
type Path = (string | symbol)[]
@@ -25,19 +23,20 @@ type SnapshotIgnore =
| Set<any>
| WeakMap<any, any>
| WeakSet<any>
- | AsRef
| Error
| RegExp
| AnyFunction
| Primitive
-type Snapshot<T> = T extends SnapshotIgnore
- ? T
- : T extends Promise<unknown>
- ? Awaited<T>
- : T extends object
- ? { readonly [K in keyof T]: Snapshot<T[K]> }
- : T
+type Snapshot<T> = T extends { $$valtioSnapshot: infer S }
+ ? S
+ : T extends SnapshotIgnore
+ ? T
+ : T extends Promise<unknown>
+ ? Awaited<T>
+ : T extends object
+ ? { readonly [K in keyof T]: Snapshot<T[K]> }
+ : T
/**
* This is not a public API.
@@ -403,9 +402,9 @@ export function snapshot<T extends object>(
return createSnapshot(target, ensureVersion(), handlePromise) as Snapshot<T>
}
-export function ref<T extends object>(obj: T): T & AsRef {
+export function ref<T extends object>(obj: T) {
refSet.add(obj)
- return obj as T & AsRef
+ return obj as T & { $$valtioSnapshot: T }
}
export const unstable_buildProxyFunction = buildProxyFunction What do you think? |
In case you missed it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please consider this approach: #850 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be good.
Snapshot<T>
use read-only collections
hey! this PR changes the
Snapshot<T>
type so that any collection types (Map, Set, WeakMap, & WeakSet) will be made read-only as well (i.e. omit mutating methods). this helps catch mistakes like the following:this is technically a build-breaking change, just like adding
readonly
was, but any users affected by typed immutability have probably fixed it already. i decided to go with two internal types (Collection
andReadonly<T>
, which usesOmit<T>
), resulting in slightly uglier type names (e.g.Readonly<Set<T>>
vs. the nativeReadonlySet<T>
), but nicer typedefs.npm run prettier