Skip to content

Commit

Permalink
fix: add scene
Browse files Browse the repository at this point in the history
  • Loading branch information
rudyxu1102 committed Jan 3, 2023
1 parent 824ea5d commit a71a63f
Showing 1 changed file with 64 additions and 23 deletions.
87 changes: 64 additions & 23 deletions active-rfcs/0000-infer-attrs.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
- 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),
- Reference Issues: [vuejs/core#3452](https://github.com/vuejs/core/issues/3452), [vuejs/core#5423](https://github.com/vuejs/core/issues/5423), [vuejs/core#6528](https://github.com/vuejs/core/discussions/6528)
- Implementation PR: [vuejs/core#7444](https://github.com/vuejs/core/pull/7444)

# Summary
Expand All @@ -12,7 +12,7 @@ I already published an npm package named [vue-ts-utils](https://github.com/rudy-
# Basic example

## Using `defineComponent`
[TS Playground](https://www.typescriptlang.org/play?jsx=1#code/JYWwDg9gTgLgBAbzgEwKYDNgDtUGELgQ5bwC+c6UBcA5AG4CuqAtDAM7MMzAA2bNAWABQwgMZE28fODgBeFBmx4CkYjAAUCYXDhgqYNgC5E2nRQgRjAZRhRsAcwA0p0s6E6oqLGijqAlIikwq6IcACGMLZGgeFsoQBGYVDGWAwg8ahQcOSkfsJiEvDiMvIAPNJg5hCyCDQAjDTkiVA1deQA9AB8wkA)
[TS Playground](https://www.typescriptlang.org/play?jsx=1#code/JYWwDg9gTgLgBAbzgEwKYDNgDtUGELgQ5bwC+c6UBcA5AG4CuqAtDAM7MMzAA2bNAWABQwgMZE28fODgBeFBmx4CkYjAAUCYXDhgqYNgC5E2nRQgRjAZRhRsAcwA0p0s6E6oqLGijqAlIikwq6IcACGMLZGgeFsoQBGYVDGWAwg8ahQcOSkfsJiEvDiMvIAPNJg5hCyCDQAjDTkiVA1deQA9AB8wkA) with Options Api
```tsx
const Comp = defineComponent({
props: {
Expand All @@ -27,32 +27,59 @@ const Comp = defineComponent({
const comp = <Comp foo={'str'} bar={1} />
```

## Using `useAttrs<T>` in `script-setup`
[TS Playground](https://www.typescriptlang.org/play?jsx=1#code/JYWwDg9gTgLgBAbzgEwKYDNgDtUGELgQ5bwC+c6UBcA5AG4CuqAtDAM7MMzAA2bNAWABQwgMZE28fODgBeFBmx4CkYjAAUCYXDhgqYNgC5E2nRQgRjAZRhRsAcwA0p0s6E62qGAzDq9EA0dEOABDGFs2OFIAShN3M3EsNggeVAA6Hgh7P302NPQLWIB6IrhJOyx7Ux1E5NSMrPUwiLSAIxCoYtKsBhBW1CgXYVdg5qgjRHIQyKR2qGMevoGoqOjhMQl4cRl5AB5pMHMIWQQaAEYacjmTs-IigD5hIA) with Composition Api
```tsx
const Comp = defineComponent({
props: {
foo: String
},
setup(props, { attrs }) {
// number
console.log(attrs.bar)
}
}, { attrs: {} as { bar: number } })

```vue
<script setup lang="ts">
const attrs = useAttrs<{bar: number}>()
</script>
const comp = <Comp foo={'str'} bar={1} />
```

<details>
<summary>Compiled Output</summary>

```js
export default /*#__PURE__*/_defineComponent({
setup(__props, { expose }) {
expose();
[TS Playground](https://www.typescriptlang.org/play?jsx=1#code/JYWwDg9gTgLgBAbzgEwKYDNgDtUGELgQ5bwC+c6UBcA5AG4CuqAtDAM7MMzAA2bNAWABQwgMZE28fODgBeFBmx4CkYjAAUCYXDhgqYNgC5E2nRQgRjAZRhRsAcwA0p0s6E62qGAzDq9EA0dEOABDGFs2OFIAShN3M3EsNggeVAA6Hgh7P302NPQLWIB6IrhJOyx7Ux1E5NSMrPUwiLSAIxCoYtKsBhBW1CgXYVdg5qgjRHIQyKR2qGMevoGoqOjhMQl4cRl5AB5pMHMIWQQaAEYacjmTs-IigD5hIA) with functional Components
```tsx
import { defineComponent, h, type SetupContext } from 'vue'

const attrs = useAttrs<{ foo: number }>()
type CompAttrs = {
bar: number
baz?: string
}

return { attrs, useAttrs, ref }
type CompEmits = {
change: (val: string) => void;
}

}, { attrs: {} as { foo: number }})"
const MyComp = defineComponent(
(_props: { foo: string }, ctx: SetupContext<CompEmits, CompAttrs>) => {
// number
console.log(ctx.attrs.bar)
// string | undefined
console.log(ctx.attrs.baz)

ctx.emit('change', '1')

return h('div')
}
)

const comp = <MyComp foo={'1'} bar={1} />
```

</details>

## Using `useAttrs<T>` in `script-setup`

```vue
<script setup lang="ts">
const attrs = useAttrs<{bar: number}>()
</script>
```

## Using `defineCustomElement`
```tsx
Expand All @@ -71,8 +98,12 @@ const Comp = defineCustomElement({
# 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.
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` option instead of using the fallthrough attributes.

Main scenes:

- Enhancing native html component, such as `button`, `input`...
- Wrapping a component from UI library, such as `el-button` from [element-plus](https://github.com/element-plus/element-plus).

# Detailed design

Expand All @@ -83,9 +114,10 @@ Due to typescript limitation from [microsoft/TypeScript#10571](https://github.co
const Comp = defineComponent<Props, Attrs>({})
```


There still has two ways to be chosen.

1. Defining the first param that already existing, just like [vuejs/rfcs#192](https://github.com/vuejs/rfcs/pull/192) did.
### 1. Defining the first param that already existing, just like [vuejs/rfcs#192](https://github.com/vuejs/rfcs/pull/192) did.
```tsx
const Comp = defineComponent({
attrs: {} as { bar: number },
Expand All @@ -100,7 +132,7 @@ const Comp = defineComponent({

const comp = <Comp foo={'str'} bar={1} />
```
2. Defining the second param as proposed.
### 2. Defining the second param as proposed.
```tsx
const Comp = defineComponent({
props: {
Expand All @@ -115,17 +147,26 @@ const Comp = defineComponent({
const comp = <Comp foo={'str'} bar={1} />
```

At last i chosen the second way that pass `attrs` type to the second params of `defineComponent`, because I think the code of the component should not be involved just for type definition.
At last I chosen the second way that passing `attrs` type to the second params of `defineComponent`, because I think the code of the component should not be involved just for type definition.


The following below 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`.
- [see for more detail cases](https://github.com/vuejs/core/pull/7444/files)
- [see for more detail cases](https://github.com/vuejs/core/pull/7444/files#diff-241bba82b0b4ebadd7a9c19ed82eed97283874b6d15ed32d62c05184e29ecb91R1195-R1306)

## `useAttrs<T>`
In the `setup-script`, the generic type of `useAttrs` will compile to the second param of `defineComponent`.
```ts

```vue
<script setup lang="ts">
const attrs = useAttrs<{bar: number}>()
</script>
```

Compiled Output:

```js
export default /*#__PURE__*/_defineComponent({
setup(__props, { expose }) {
expose();
Expand Down

0 comments on commit a71a63f

Please sign in to comment.