Search code examples
typescriptvue.jsvuejs3vue-composition-apivue-script-setup

How to use dynamic prop type in Vue 3 script setup using defineprop and interface


I'm creating a component that takes in an array of data (using typed props based on an interface) and then pass in a second prop that dynamically selects the the property I'd like to reference in the data object.

I'm using Vue 3 script setup syntax with Typescript and defineProps.

<script setup lang="ts">
interface DataRow {
   'id': number
   'height': number
   'strideLength': number
   'distanceTravelled': number
   'timestamp': Date
}

const props = defineProps<{
   data: DataRow[]
   xAxis: string 
   yAxis: string
}>
</script>

<template>
X Axis: {{ props.data[xAxis] }}
Y Axis: {{ props.data[YAxis] }}
<pre>
{{ data }}
</pre>
</template>

I'm trying to pass in one of the interface properties so that I can dynamically select what I'm displaying on the x/y axis of a plot. Currently, I'm using a string but I'm getting linter errors given that it's untyped.

const props = defineProps<{
   data: DataRow[]
   xAxis: string  <- this should only be properties of my DataRow interface
   yAxis: string <- this should only be properties of my DataRow interface
}>
<my-component
:data="[{id: 1, height: 2, strideLength: 0.5, distanceTravelled: 5, timestamp: new Date()}]"
:xAxis="timestamp"
:yAxis="height" />

Is there a better way of doing this?


Solution

  • Try to use the keyof Type Operator :

    <script setup lang="ts">
    interface DataRow {
       'id': number
       'height': number
       'strideLength': number
       'distanceTravelled': number
       'timestamp': Date
    }
    
    const props = defineProps<{
       data: DataRow[]
       xAxis: keyof DataRow
       yAxis: keyof DataRow
    }>
    </script>
    
    <template>
    X Axis: {{ props.data[xAxis] }}
    Y Axis: {{ props.data[YAxis] }}
    <pre>
    {{ data }}
    </pre>
    </template>