浏览代码

fix(types/defineModel): allow getter and setter types to be unrelated (#11699)

close #11697
Tycho 1 年之前
父节点
当前提交
fe07f70736

+ 45 - 0
packages-private/dts-test/setupHelpers.test-d.ts

@@ -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', () => {

+ 28 - 24
packages/runtime-core/src/apiSetupHelpers.ts

@@ -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')

+ 7 - 1
packages/runtime-core/src/helpers/useModel.ts

@@ -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,