-
Notifications
You must be signed in to change notification settings - Fork 546
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
rudyxu
committed
Jan 1, 2023
1 parent
cdee004
commit 085f62b
Showing
1 changed file
with
79 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
- Start Date: 2023-01-01 | ||
- Target Major Version: 3.x | ||
- Reference Issues: [vuejs/core#3452](https://github.com/vuejs/core/issues/3452), [vuejs/core#5423](https://github.com/vuejs/core/issues/5423), | ||
- Implementation PR: [vuejs/core#]() | ||
|
||
# Summary | ||
|
||
Allow to infer `attrs` when passing type on the second param of`defineComponent`. And In the `setup-script`, passing generic type on the `useAttrs<T>` make `attrs` inferred. | ||
|
||
I already publish an npm package named [vue-ts-utils](https://github.com/rudy-xhd/vue-ts-utils), so that you can use `defineComponent` to infer attrs in advance. | ||
|
||
# Basic example | ||
|
||
## Using `defineComponent` directly | ||
[TS Playground](https://www.typescriptlang.org/play?jsx=1#code/JYWwDg9gTgLgBAbzgEwKYDNgDtUGELgQ5bwC+c6UBcA5AG4CuqAtDAM7MMzAA2bNAWABQwgMZE28fODgBeFBmx4CkYjAAUCYXDhgqYNgC5E2nRQgRjAZRhRsAcwA0p0s6E6oqLGijqAlIikwq6IcACGMLZGgeFsoQBGYVDGWAwg8ahQcOSkfsJiEvDiMvIAPNJg5hCyCDQAjDTkiVA1deQA9AB8wkA) | ||
```tsx | ||
const Comp = defineComponent({ | ||
props: { | ||
foo: String | ||
} | ||
}, { attrs: {} as { bar: number } }) | ||
|
||
const comp = <Comp foo={'1'} bar={1} /> | ||
``` | ||
|
||
## Using `useAttrs<T>` in `script-setup` | ||
|
||
```vue | ||
<script setup lang="ts"> | ||
const attrs = useAttrs<{bar: number}>() | ||
</script> | ||
``` | ||
|
||
<details> | ||
<summary>Compiled Output</summary> | ||
|
||
```js | ||
export default /*#__PURE__*/_defineComponent({ | ||
setup(__props, { expose }) { | ||
expose(); | ||
|
||
const attrs = useAttrs<{ foo: number }>() | ||
|
||
return { attrs, useAttrs, ref } | ||
} | ||
|
||
}, { attrs: {} as { foo: number }})" | ||
``` | ||
</details> | ||
# Motivation | ||
This proposal is mainly to infer `attrs` using `defineComponent`. | ||
When using typescript in Vue3, the fallthrough attributes is unable to be used. It's not appropriate obviously that only one can be chosen from `typescript` and `the fallthrough attributes`. In most cases, we choose `typescript` and set attributes to `props` options instead of using the fallthrough attributes. | ||
# Detailed design | ||
## `defineComponent` | ||
Due to typescript limitation from [microsoft/TypeScript#10571](https://github.com/microsoft/TypeScript/issues/10571), it's not possable to allow skipping generics in the `defineComponent` like below. | ||
```tsx | ||
// it's not work | ||
const Comp = defineComponent<Props, Attrs>({}) | ||
``` | ||
So I propose to pass `attrs` type to the second params of `defineComponent`. | ||
The following blow is the design details. | ||
- `attrs` is inferred to `{ class: unknown; style: unknown }` when the value of the second param is `undefined` | ||
- `attrs` is lower priority than `props`. | ||
## `useAttrs` | ||
In the `setup-script`, the generic type of `useAttrs` will compile to the second param of `defineComponent` | ||
# Unresolved questions | ||
Naming suggestions or improvements on the API are welcome. | ||