diff --git a/packages-private/dts-test/setupHelpers.test-d.ts b/packages-private/dts-test/setupHelpers.test-d.ts index 64c944e0be2..4074176ff98 100644 --- a/packages-private/dts-test/setupHelpers.test-d.ts +++ b/packages-private/dts-test/setupHelpers.test-d.ts @@ -427,6 +427,51 @@ describe('defineModel', () => { defineModel({ 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(modelVal.value) + modelVal.value = 1 + modelVal.value = undefined + // @ts-expect-error + modelVal.value = 'foo' + + const [modelVal2] = modelVal + expectType(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(count.value) + count.value = 1 + count.value = undefined + // @ts-expect-error + count.value = 'foo' + + const [count2] = count + expectType(count2.value) + count2.value = 1 + count2.value = undefined + // @ts-expect-error + count2.value = 'foo' + } }) describe('useModel', () => { diff --git a/packages/runtime-core/src/apiSetupHelpers.ts b/packages/runtime-core/src/apiSetupHelpers.ts index 90bde3aebd2..33817818a93 100644 --- a/packages/runtime-core/src/apiSetupHelpers.ts +++ b/packages/runtime-core/src/apiSetupHelpers.ts @@ -240,12 +240,15 @@ export function defineSlots< return null as any } -export type ModelRef = Ref & - [ModelRef, Record] +export type ModelRef = Ref< + G, + S +> & + [ModelRef, Record] -export type DefineModelOptions = { - get?: (v: T) => any - set?: (v: T) => any +export type DefineModelOptions = { + get?: (v: T) => G + set?: (v: S) => any } /** @@ -281,27 +284,28 @@ export type DefineModelOptions = { * const count = defineModel('count', { default: 0 }) * ``` */ -export function defineModel( - options: { required: true } & PropOptions & DefineModelOptions, -): ModelRef -export function defineModel( - options: { default: any } & PropOptions & DefineModelOptions, -): ModelRef -export function defineModel( - options?: PropOptions & DefineModelOptions, -): ModelRef -export function defineModel( - name: string, - options: { required: true } & PropOptions & DefineModelOptions, -): ModelRef -export function defineModel( +export function defineModel( + options: ({ default: any } | { required: true }) & + PropOptions & + DefineModelOptions, +): ModelRef + +export function defineModel( + options?: PropOptions & DefineModelOptions, +): ModelRef + +export function defineModel( name: string, - options: { default: any } & PropOptions & DefineModelOptions, -): ModelRef -export function defineModel( + options: ({ default: any } | { required: true }) & + PropOptions & + DefineModelOptions, +): ModelRef + +export function defineModel( name: string, - options?: PropOptions & DefineModelOptions, -): ModelRef + options?: PropOptions & DefineModelOptions, +): ModelRef + export function defineModel(): any { if (__DEV__) { warnRuntimeUsage('defineModel') diff --git a/packages/runtime-core/src/helpers/useModel.ts b/packages/runtime-core/src/helpers/useModel.ts index 8180fb32c47..37fd1d719b0 100644 --- a/packages/runtime-core/src/helpers/useModel.ts +++ b/packages/runtime-core/src/helpers/useModel.ts @@ -10,7 +10,13 @@ export function useModel< M extends PropertyKey, T extends Record, K extends keyof T, ->(props: T, name: K, options?: DefineModelOptions): ModelRef + G = T[K], + S = T[K], +>( + props: T, + name: K, + options?: DefineModelOptions, +): ModelRef export function useModel( props: Record, name: string,