]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(types/defineModel): allow getter and setter types to be unrelated (#11699)
authorTycho <jh.leong@outlook.com>
Tue, 3 Sep 2024 09:47:50 +0000 (17:47 +0800)
committerGitHub <noreply@github.com>
Tue, 3 Sep 2024 09:47:50 +0000 (17:47 +0800)
close #11697

packages-private/dts-test/setupHelpers.test-d.ts
packages/runtime-core/src/apiSetupHelpers.ts
packages/runtime-core/src/helpers/useModel.ts

index 64c944e0be22d8609e91bc7aff542ffb6b9aaaf5..4074176ff982e819fb6d3ebeb71e20a50557d153 100644 (file)
@@ -427,6 +427,51 @@ describe('defineModel', () => {
   defineModel<string>({ default: 123 })
   // @ts-expect-error unknown props option
   defineModel({ foo: 123 })
+
+  // unrelated getter and setter types
+  {
+    const modelVal = defineModel({
+      get(_: string[]): string {
+        return ''
+      },
+      set(_: number) {
+        return 1
+      },
+    })
+    expectType<string | undefined>(modelVal.value)
+    modelVal.value = 1
+    modelVal.value = undefined
+    // @ts-expect-error
+    modelVal.value = 'foo'
+
+    const [modelVal2] = modelVal
+    expectType<string | undefined>(modelVal2.value)
+    modelVal2.value = 1
+    modelVal2.value = undefined
+    // @ts-expect-error
+    modelVal.value = 'foo'
+
+    const count = defineModel('count', {
+      get(_: string[]): string {
+        return ''
+      },
+      set(_: number) {
+        return ''
+      },
+    })
+    expectType<string | undefined>(count.value)
+    count.value = 1
+    count.value = undefined
+    // @ts-expect-error
+    count.value = 'foo'
+
+    const [count2] = count
+    expectType<string | undefined>(count2.value)
+    count2.value = 1
+    count2.value = undefined
+    // @ts-expect-error
+    count2.value = 'foo'
+  }
 })
 
 describe('useModel', () => {
index 90bde3aebd25bc5525098df4573102be86ffecde..33817818a9310ff747e48cda86494ab6aa30359b 100644 (file)
@@ -240,12 +240,15 @@ export function defineSlots<
   return null as any
 }
 
-export type ModelRef<T, M extends PropertyKey = string> = Ref<T> &
-  [ModelRef<T, M>, Record<M, true | undefined>]
+export type ModelRef<T, M extends PropertyKey = string, G = T, S = T> = Ref<
+  G,
+  S
+> &
+  [ModelRef<T, M, G, S>, Record<M, true | undefined>]
 
-export type DefineModelOptions<T = any> = {
-  get?: (v: T) => any
-  set?: (v: T) => any
+export type DefineModelOptions<T = any, G = T, S = T> = {
+  get?: (v: T) => G
+  set?: (v: S) => any
 }
 
 /**
@@ -281,27 +284,28 @@ export type DefineModelOptions<T = any> = {
  * const count = defineModel<number>('count', { default: 0 })
  * ```
  */
-export function defineModel<T, M extends PropertyKey = string>(
-  options: { required: true } & PropOptions<T> & DefineModelOptions<T>,
-): ModelRef<T, M>
-export function defineModel<T, M extends PropertyKey = string>(
-  options: { default: any } & PropOptions<T> & DefineModelOptions<T>,
-): ModelRef<T, M>
-export function defineModel<T, M extends PropertyKey = string>(
-  options?: PropOptions<T> & DefineModelOptions<T>,
-): ModelRef<T | undefined, M>
-export function defineModel<T, M extends PropertyKey = string>(
-  name: string,
-  options: { required: true } & PropOptions<T> & DefineModelOptions<T>,
-): ModelRef<T, M>
-export function defineModel<T, M extends PropertyKey = string>(
+export function defineModel<T, M extends PropertyKey = string, G = T, S = T>(
+  options: ({ default: any } | { required: true }) &
+    PropOptions<T> &
+    DefineModelOptions<T, G, S>,
+): ModelRef<T, M, G, S>
+
+export function defineModel<T, M extends PropertyKey = string, G = T, S = T>(
+  options?: PropOptions<T> & DefineModelOptions<T, G, S>,
+): ModelRef<T | undefined, M, G | undefined, S | undefined>
+
+export function defineModel<T, M extends PropertyKey = string, G = T, S = T>(
   name: string,
-  options: { default: any } & PropOptions<T> & DefineModelOptions<T>,
-): ModelRef<T, M>
-export function defineModel<T, M extends PropertyKey = string>(
+  options: ({ default: any } | { required: true }) &
+    PropOptions<T> &
+    DefineModelOptions<T, G, S>,
+): ModelRef<T, M, G, S>
+
+export function defineModel<T, M extends PropertyKey = string, G = T, S = T>(
   name: string,
-  options?: PropOptions<T> & DefineModelOptions<T>,
-): ModelRef<T | undefined, M>
+  options?: PropOptions<T> & DefineModelOptions<T, G, S>,
+): ModelRef<T | undefined, M, G | undefined, S | undefined>
+
 export function defineModel(): any {
   if (__DEV__) {
     warnRuntimeUsage('defineModel')
index 8180fb32c472eac8d946e31094382eb71f2ba190..37fd1d719b006bacd8a6dc3310f63cb2707a168d 100644 (file)
@@ -10,7 +10,13 @@ export function useModel<
   M extends PropertyKey,
   T extends Record<string, any>,
   K extends keyof T,
->(props: T, name: K, options?: DefineModelOptions<T[K]>): ModelRef<T[K], M>
+  G = T[K],
+  S = T[K],
+>(
+  props: T,
+  name: K,
+  options?: DefineModelOptions<T[K], G, S>,
+): ModelRef<T[K], M, G, S>
 export function useModel(
   props: Record<string, any>,
   name: string,