core icon indicating copy to clipboard operation
core copied to clipboard

feat(types): support inferring attrs

Open rudyxu1102 opened this issue 3 years ago • 14 comments

Related

  • #3452
  • #5423
  • #6528
  • #7546
  • #7981
  • #8264
  • #8508
  • #8620
  • #8902
  • #9272

RFC

  • https://github.com/vuejs/rfcs/pull/477

Specific scenes

1. Wrapping an html element

import { defineComponent, type ImgHTMLAttributes, type AttrsType } from 'vue';

const MyImg = defineComponent({
    props: {
        foo: String
    },
    attrs: Object as AttrsType<ImgHTMLAttributes>,
    created() {
        this.$attrs.class // any
        this.$attrs.style // StyleValue | undefined
        this.$attrs.onError // ((payload: Event) => void) | undefined
        this.$attrs.src // string | undefined
    },
    render() {
        return <img {...this.$attrs} />
    }
});

<MyImg class={'str'} style={'str'} src={'https://xxx.com/aaa.jpg'} onError={(e) => {
  e; // Event
}}/>;

2. Wrapping a Vue component

import { defineComponent, type AttrsType } from 'vue';

const Comp = defineComponent({
    props: {
        foo: String
    },
    emits: {
        baz: (val: number) => true
    },
    render() {
        return <div>{this.foo}</div>
    }
});

const MyComp = defineComponent({
    props: {
        bar: Number
    },
    attrs: Object as AttrsType<typeof Comp>,
    created() {
        this.$attrs.class // unknown
        this.$attrs.style // unknown
        this.$attrs.onBaz; // ((val: number) => any) | undefined
        this.$attrs.foo; // string | undefined
    },
    render() {
        return <Comp {...this.$attrs} />
    }
});

<MyComp class={'str'} style={'str'} bar={1} foo={'str'} onBaz={(val) => { 
    val; // number
}} />;

rudyxu1102 avatar Jan 01 '23 10:01 rudyxu1102

Deploy Preview for vuejs-coverage failed.

Name Link
Latest commit cc506ce99b1aa04c65522e8879fca9853fceed09
Latest deploy log https://app.netlify.com/sites/vuejs-coverage/deploys/63b5a24c5e5c910008a149fe

netlify[bot] avatar Jan 01 '23 10:01 netlify[bot]

Deploy Preview for vue-sfc-playground failed.

Name Link
Latest commit cc506ce99b1aa04c65522e8879fca9853fceed09
Latest deploy log https://app.netlify.com/sites/vue-sfc-playground/deploys/63b5a24c075f5b0007a104a6

netlify[bot] avatar Jan 04 '23 16:01 netlify[bot]

@yyx990803 we need this in oku-ui, for example we need to go back the

element types so that volar can suggest user auto-suggestion with both props and attrs types.

can you review and include this?

productdevbook avatar May 08 '23 16:05 productdevbook

Looks great. Could you please rebase your branch to resolve conflicts?

I guess this feature will more be like defineSlots. Without adding runtime code, but adding only TS types.

sxzz avatar Aug 23 '23 20:08 sxzz

Size Report

Bundles

File Size Gzip Brotli
runtime-dom.global.prod.js 85.8 kB 32.6 kB 29.5 kB
vue.global.prod.js 132 kB 49.3 kB 44.3 kB

Usages

Name Size Gzip Brotli
createApp 47.9 kB 18.8 kB 17.2 kB
createSSRApp 50.6 kB 19.9 kB 18.2 kB
defineCustomElement 50.3 kB 19.6 kB 17.9 kB
overall 61.2 kB 23.7 kB 21.6 kB

github-actions[bot] avatar Aug 30 '23 13:08 github-actions[bot]

I would love to see this feature merged as well, and seeing as it's a typing only feature, I would love to see it show up in 2.7 as well. Currently creating a component that thinly wraps another component is pretty tedious, because you have to either redeclare all inner component props on the wrapper component, or you have to sacrifice type safety/intellisense.

Aaron-Pool avatar Sep 12 '23 13:09 Aaron-Pool

I would love to see this feature merged as well, and seeing as it's a typing only feature, I would love to see it show up in 2.7 as well. Currently creating a component that thinly wraps another component is pretty tedious, because you have to either redeclare all inner component props on the wrapper component, or you have to sacrifice type safety/intellisense.

Nice call. It will be released in the future. Here is the Merge Request about this feature of Vue2. Also, you can use vue-ts-utils for workaround in the Vue2 or Vue3. If you have any questions about vue-ts-utils package, please let me know it and I would love to fix it. @Aaron-Pool

rudyxu1102 avatar Sep 25 '23 12:09 rudyxu1102

@rudyxu1102 Thanks for the PR

Managed to test your PR

It works with defineComponent(TS/TSX) way

But in .vue(SFC) useAttrs does not accept any argument/generics

const attrs = useAttrs<{ // Expected 0 type arguments, but got 1.
  bar: string
}>()

sadeghbarati avatar Oct 13 '23 18:10 sadeghbarati

Could you please REBASE your branch due the minor branch has been also rebased.

sxzz avatar Oct 27 '23 14:10 sxzz

Could you please REBASE your branch due the minor branch has been also rebased.

@sxzz done

rudyxu1102 avatar Oct 27 '23 17:10 rudyxu1102

This is much needed, thanks!

amritk avatar Nov 08 '23 21:11 amritk