I'm currently working on an application that includes a chart, and I'm facing an issue while trying to populate the chart with data from my store. The error occurs when I attempt to pass the chartData object through props to the data property of the line Chart (3rd line in the chart component).
Property 'datasets' is missing in type 'Record<string, any>' but required in type 'ChartData<"line", (number | Point | null)[], unknown>'.ts(2741)
index.d.ts(3790, 3): 'datasets' is declared here.
types.d.ts(12, 5): The expected type comes from property 'data' which is declared here on type '{ readonly data: ChartData<"line", (number | Point | null)[], unknown>;'.
The chart component is being rendered in the User.vue file.
<template>
<div class="profile-container">
<div class="user-container card">
<img class="round-image" src="https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_1280.png">
<div class="username">{{user?.name}}</div>
</div>
<div class="card statistics-container">
<div class="rank"><span><font-awesome-icon class="icon" icon="fa-solid fa-crown" /></span> 2nd place</div>
<div class="statistics">
<div><span>MAX WPM:</span> {{ user?.analytics.max_wpm }}</div>
<div><span>AVG WPM:</span> {{ user?.analytics.average_wpm }}</div>
<div><span>AVG ACC:</span> {{ user?.analytics.average_accuracy }}%</div>
<div><span>TOTAL TESTS:</span> {{ user?.analytics.number_of_tests }}</div>
</div>
</div>
<chart class="chart" :chartData="chartData" :chartOptions="chartOptions"></chart>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import Chart from '../components/Profile/Chart.vue'
import { useUserStore } from '~/store/User/UserStore';
import { ChartType } from 'chart.js';
const { $axios } = useNuxtApp();
const userStore = useUserStore();
const showPassword = ref(false);
const chartData = computed(() =>{
const currentUser = user.value; // Use .value shorthand
const typingTestResults = currentUser?.typingTestResults;
return {
type: 'line' as ChartType,
labels: typingTestResults?.map(result => result.created_at),
datasets: [
{
label: 'WPM',
data: typingTestResults?.map(result => result.wpm),
acc: typingTestResults?.map(result => result.accuracy),
time: typingTestResults?.map(result => result.duration_seconds),
backgroundColor: 'rgba(255, 174, 0, 0.2)',
borderColor: color: 'rgb(255, 174, 0)',
borderWidth: 3,
pointRadius: 6,
tension: 0.1,
}
],
};
});
const chartOptions = {
responsive: true,
maintainAspectRatio: false,
scales: {
x: {
title: {
display: true,
text: 'Dates',
font: {
size: 16,
family: 'RobotoMono'
}
}
},
y: {
title: {
display: true,
text: 'WPM',
font: {
size: 16,
family: 'RobotoMono'
}
}
}
},
plugins: {
tooltip: {
mode: 'index',
intersect: false,
callbacks: {
label: (context) => {
const wpm = `- WPM: ${context.parsed.y}`;
const acc = `- ACC: ${context.dataset.acc[context.dataIndex]}%`;
const time = `- Time: ${context.dataset.time[context.dataIndex]}s`;
return [wpm, acc, time];
}
},
displayColors: false,
bodyFont: {
size: 17,
family: 'RobotoMono'
}
},
legend: {
display: false
}
}
}
const togglePasswordVisibility = () => {
showPassword.value = !showPassword.value;
};
const user = computed(()=>{
return userStore.user;
})
onMounted(async () =>{
if(!userStore.user){
userStore.user = (await $axios.get('/user')).data.data;
}
console.log(user);
})
</script>
Here's how my Chart component has been defined:
<template>
<div>
<Line :data="chartData" :options="chartOptions"></Line>
</div>
</template>
<script setup lang="ts">
import { Line } from 'vue-chartjs'
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend
} from 'chart.js'
ChartJS.register(
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend
)
const props = defineProps({
chartData: {
type: Object,
required: true
},
chartOptions: {
type: Object,
required: true
}
});
And this is how my store looks like:
import { TypingTestResult, User } from './../../types/User';
import { defineStore } from 'pinia';
export const useUserStore = defineStore('user', {
state: () => ({
user: {
id: 0,
name: '',
email: '',
typingTestResults: [] as TypingTestResult[],
analytics: {
max_wpm: 0,
average_wpm: 0,
average_accuracy: 0,
number_of_tests: 0,
},
} as User,
}),
});