question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Feature Request: support generic emits

See original GitHub issue
<script lang="ts">
declare const Bar: new <T>(props: { readonly value: T }) => {
  $props: typeof props;
  $emit: {
    (event: "update:value", e: T): void;
  };
};
const console = window.console;
</script>
<script setup lang="ts">
</script>
<template>
  <div id="app">
    <Bar :value="1" @update:value="console.log($event)" />
  </div>
</template>

The type of $event should be number

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
Everttcommented, Apr 4, 2022

@xiaoxiangmoe okay thank you. For now I found an acceptable solution, which looks like this:

import { VNode } from 'vue'

const column_options = [
  "checked",
  "index",
  "filename",
  "name",
  "quantity",
  "material",
  "thickness",
  "process",
  "operations",
  "reference",
  "certificates",
  "is_valid",
  "price",
  "total",
  "actions"
] as const

// If I first define a type with a defined finite set of possible keys
type A<T> = {
  [key in typeof column_options[number]]: ({ column, index, row } :{
    readonly column: key
    readonly index: number
    readonly row: T
  }) => VNode[] | undefined
}

// And *then* define a type with keys that could be any string
type B<T> = {
  [key in string]: ({ column, index, row } :{
    readonly column: key
    readonly index: number
    readonly row: T
  }) => VNode[] | undefined
}

// And then combine the two, then for some reason
// Volar seems to accept that every and any slot can have a defined data type.
// As opposed to before, where Volar would just say that data of all slots was just of type any.
declare const VClientTable: new <T>(props: { readonly data: T[] }) => {
  $props: typeof props;
  $slots: A<T> & B<T>
}

The result is that any slot whose name is one of the column_options, I will get the exact type that I want, namely this:

image

And any slot whose name is not one of the column_options, I will get nearly the exact type I want:

image

Like it would’ve been nice if column had still been "quantityyyyy", but this is already miles better than what I got before. Because when I asked you the question a few days ago, data was just always any.

But anyhow, I actually wanted to ask you one more question. I hope I’m not asking too much.

In your example, and also in my code, you are giving the Bar component its type definition from within another component; from within the component that’s using the Bar component. Do you know if it’s possible to give the Bar component its type definition from within the Bar component itself?

I know it’s possible to define an export type inside Bar.vue, but then in every component where you want to use Bar, you’d need to do something like this:

import BarComp, { BarType } from "./Bar.vue"
const Bar = BarComp as BarType<number>

I’m hoping there’s a more elegant solution, where I can just import Bar from "./Bar.vue" and by simply using it like your example: <Bar :value="1" @update:value="console.log($event)" />, the type of $event is implied through the generics.

Do you know a way to do that from within Bar.vue?

1reaction
xiaoxiangmoecommented, Mar 7, 2022

In vue 2:

<script lang="ts">
import { VNode } from 'vue';

declare const Bar: new <T>(props: { readonly value: T; readonly 'onUpdate:value'?: (value: T) => void }) => {
    $props: typeof props;
    $scopedSlots: {
        default?: ({ foo }: { readonly foo: T }) => VNode[] | undefined;
    };
};
const console = window.console;
</script>
<script setup lang="ts"></script>
<template>
    <div id="app">
        <Bar :value="1" @update:value="console.log($event)">
            <template #default="{ foo }">
                {{ foo + 1 }}
            </template>
        </Bar>
    </div>
</template>

In vue 3:

change $scopedSlots to $slots

Read more comments on GitHub >

github_iconTop Results From Across the Web

Feature request response email templates - LiveAgent
Feature requests are messages that customers send to inquire about a feature that is not included in your product or service. Receiving feature...
Read more >
Feature Requests: What are they and how to manage them
Feature requests are a form of product feedback you may frequently encounter as a SaaS product manager. They typically come in the form...
Read more >
The right way to respond to feature requests - Inside Intercom
It's easy to respond to these feature requests with a generic “Keep an eye on Twitter for updates” response or a pre-canned “We'll...
Read more >
10 Tips to Improve Your Feature Request Responses - Nicereply
Feature requests are the best way to improve your product. Here are ten tips to make the most out of them.
Read more >
Documentation - Decorators - TypeScript
A Decorator is a special kind of declaration that can be attached to a class declaration, method, accessor, property, or parameter. Decorators use...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found