ITADN
vuejs/core/Issues

defineModel: named model with PropType + factory default infers wrong generic (regression from #14968)

#15096Openyeonyew 创建于 2026-07-16
scope: typeshas workaround
Y
yeonyewcommented
### Vue version 3.5.39 ### Link to minimal reproduction https://play.vuejs.org/#eNqtk81qGzEQx19l0MUJmDXUTaGLbUhKDi20DY1JD1Gold3ZjWJZEvpwbcwee+sjtC/XJ+lIi50EQk65rWb+M/Obj92xU2uLdURWsomvnLQBPIZoQQndTjkLnrMZ13JljQsQthZhBxfO2Hn67KBxZgUDSjDgmuvRCP79/Q1nsS1hfglSN+g8zHtVuENY1NiIqMICGlEF47Ygg0fVkNQHFDWYBhapymKYs1UieqlbEOBtdNJE3zOgc8YBuSqEq4gwLk6K8fuC68pQIrh1ZokapkDlpMbPpkZ1NFhLL2+lkmE7GMKOa8i5Sjh1TmxB+ENfEx8cVb2+mREFpCSJuYSjY5jO4PqGrN3xvt8/v+C7cUvhTNR1CVbq3GmLGp2sADdWyUoGtd3DNXKD9VO2h4KPKd+8DuZk1C+W1kiPgCurREB6AUxquZ7tdvt5dR3Qo+fruskoeVP8IYYN6SCoi0a2xb03mq4mA3JWmZWVCt1XGyR1yVnZoyefUMr8/JRtwUXMsDnmDqvlM/Z7v0k2zi4cenRr5OzgC8K1GHr3+eUX3ND3wbkydVSkfsH5Db1RMTH2sjNaGmE/0mXaj/neabhzf74JqP2+qQSalF3Wc0aX/+GF1h9wx8XbHEc7oSn+WNOPQWoaYH+6yRb81cF6Urwrxqz7D9k1OqM= ### Steps to reproduce In the reproduction, `broken` declares a named model with a runtime `type: PropType<string[]>` plus a factory `default: () => []`. `fixed` declares the same thing but with the generic pinned explicitly (`defineModel<string[]>(...)`). Run the type checker (or `vue-tsc --noEmit` locally) over this SFC. ### What is expected? Both `broken` and `fixed` should type-check cleanly — this is the recommended pattern for avoiding shared mutable state (per #14966 / #14968): a factory default combined with a runtime `PropType` declaration. ### What is actually happening? Only `broken` fails. TS infers the generic `T` from the `default` factory function's own type (`() => never[]`) instead of from the `type: PropType<string[]>` field: error TS2769: No overload matches this call. Overload 1 of 4, '(name: string, options: ({ required: true; } | { default: DefineModelDefault<() => never[]>; }) & Omit<PropOptions<() => never[], () => never[]>, "default"> & DefineModelOptions<...>): ModelRef<...>', gave the following error. Type 'PropType<string[]>' is not assignable to type 'true | PropType<() => never[]> | null | undefined'. Type 'new (...args: any[]) => string[]' is not assignable to type 'true | PropType<() => never[]> | null | undefined'. Type 'new (...args: any[]) => string[]' is not assignable to type 'new (...args: any[]) => () => never[]'. Type 'string[]' is not assignable to type '() => never[]'. Type 'string[]' provides no match for the signature '(): never[]'. Overload 2 of 4, '(name: string, options?: DefineModelRuntimeOptions<string[], string[], string[]> | undefined): ModelRef<string[] | undefined, string, string[] | undefined, string[] | undefined>', gave the following error. Object literal may only specify known properties, and 'default' does not exist in type 'DefineModelRuntimeOptions<string[], string[], string[]>'. his is a regression from #14968 (landed in 3.5.39), which introduced `DefineModelDefault<T> = InferDefault<Data, T>` for the named-model overload. When both a runtime `type: PropType<T>` field and a factory `default` are present on the same options object, TS resolves `T` from the `default` field first, breaking a pattern that worked prior to 3.5.39. **Workaround:** explicitly pin the generic, as shown by `fixed` in the reproduction: ```ts const fixed = defineModel<string[]>('visibility2', { type: Array as PropType<string[]>, default: () => [], }) ``` ### System Info ```shell vue: 3.5.39 vue-tsc: 3.3.7 typescript: 5.7.3 ``` ### Any additional comments? Related to / regression from #14966 and #14968. Only reproduces on the **named** `defineModel(name, options)` overload when `type`/`PropType` and a factory `default` are combined; the unnamed `defineModel<T>({ ... })` form with an explicit generic is unaffected.
0 条评论