-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
fix(apiWatch): correct type inference for reactive array #11036
Conversation
1d90f9b
to
ec2213f
Compare
Size ReportBundles
Usages
|
98655af
to
6ea95a4
Compare
/ecosystem-ci run |
📝 Ran ecosystem CI: Open
|
From ecosystem-ci this PR seems to break VueUse's dts build: https://github.com/vuejs/ecosystem-ci/actions/runs/9296270402/job/25584547935#step:7:77 |
Fixed now, could you please rerun the ecosystem CI? Thanks :) |
/ecosystem-ci run |
📝 Ran ecosystem CI: Open
|
1042d9d
to
482e669
Compare
To address the issue at the type level, reactive array and normal arrays must be differentiated in the watch API type inference. Currently, the code can't distinguish between them, as shown below: // Both are inferred as Ref<number>[]
const arr1 = [ref(1)]
const arr2 = reactive(arr1) To solve this, need to mark reactive array types specially. I considered two ways:
However, both ways introduce breaking changes: declare const ReactiveMarkerSymbol: unique symbol
export declare class ReactiveMarker {
private [ReactiveMarkerSymbol]?: void
}
export type Reactive<T> = UnwrapNestedRefs<T> & ReactiveMarker
export type Reactive2<T> = UnwrapNestedRefs<T> & {
[ReactiveMarkerSymbol]?: void
}
type Foo = { count: number }
declare const vPrivate: Reactive<Foo>
declare const vSymbol: Reactive2<Foo>
{
let a: { count: number } = vSymbol // ok
let b: { count: number } = vPrivate // ok
}
{
let a: Record<string, number> = vSymbol // ok
// Breaking change: Assigning to a Record (or index signature) will result in an error
// because the Class can use the Interface for declaration merging
let b: Record<string, number> = vPrivate // error!
}
{
// Breaking change: the symbol key leaked when using keyof
type a = keyof typeof vSymbol // "count" | typeof ReactiveMarkerSymbol
// ok
type b = keyof typeof vPrivate // "count"
}
{
type Vals<T> = T[keyof T]
// Breaking change: the value of the symbol key is leaked when getting Vals
type a = Vals<typeof vSymbol> // number | undefined
// ok
type b = Vals<typeof vPrivate> // number
} To avoid these breaking changes, I've decided to mark only reactive arrays specially: export declare class ReactiveMarker {
private [ReactiveMarkerSymbol]?: void
}
export type Reactive<T> = UnwrapNestedRefs<T> &
(T extends readonly any[] ? ReactiveMarker : {}) Due to the special nature of arrays in TypeScript, this avoids the issues mentioned: declare const arr: Reactive<[string]>
declare let record: Record<number, string>
record = arr // ok Any advice on these changes or a better approach? |
could you please rerun the ecosystem-ci |
/ecosystem-ci run |
📝 Ran ecosystem CI: Open
|
Great work! |
close #9416.