CodeDredd / pinia-orm

The Pinia plugin to enable Object-Relational Mapping access to the Pinia Store.
https://pinia-orm.codedredd.de/
MIT License
453 stars 39 forks source link

TypeScript definitions for models cause null values. #15

Closed tintin10q closed 2 years ago

tintin10q commented 2 years ago

Thanks you for solving the flush thing! This is a very nice thing to have.

Now I have this other problem. I would love to add types to my models to get editor suggestions and the general benefits of Typescript. I tried to add the type definitions as outlined here: https://next.vuex-orm.org/guide/model/decorators.html. When I did this I did get the type information and nice type suggestions in my ide so that works.

But as soon as I defined a type for a field (either with or without a decorator) the field becomes null when queried.

Maybe I am missing something?

Reproduction

Use this simple model:

import { Model, Uid, Str } from "pinia-orm";

export default class Todo extends Model {
  static entity = "Todo";

  // static fields() {
  //   return {
  //     id: this.uid(),
  //     text: this.string(""),
  //     name: this.string(""),
  //   };
  // }
  //
  // id!: string;
  // text!: number;
  // name!: number;

  @Uid()
  id!: string;

  @Str("Todo Text")
  text!: string;

  @Str("Todo Name")
  name!: string;
}

You can try defining with the decorators or using the commented out fields static method and the type definitions.

Now have a component like this:

<template>
  <button @click="todo.save({text:"Fix TS support", name:"TS Todo"})">Add todo</button> 
  <button @click="todo.flush()">Clear Todos</button>
  <span>{{all_todo_text}}</span>
<template>

<script setup lang="ts">
import { computed } from "vue";
import Todo from "@/Todo";

const todo = useRepo(Todo);
const all_todo_text = computed(() => todo.all().map((t) => t.text));
</script>

Steps to reproduce the behavior

  1. Build the above code
  2. Click the add todo button
  3. Notice that the todo texts are null
  4. Comment out the decorators and comment in the static field method
  5. Notice that the todos are now the default given in the decorator (Even though I did give a value in save)
  6. Add another todo and notice that the new todos do have the value given in the .save
  7. Now if you comment in the type definitions below the field method everything goes to null again.

Expected behavior

I would expect the values of the model to not be affect (turn to null) by the type definitions.

Actual behavior

When adding type definitions to models the values of the fields turn to null and in the case of decorators the values given in .save are ignored. With this the type definitions are not useable.

tintin10q commented 2 years ago

Let me know if you are able to reproduce this. Weirdly enough I made this code sandbox and in there it did not occur for me:

https://codesandbox.io/s/heuristic-http-okdsqz

Could it maybe have something to do with that I use the persistent pinia plugin and async localforage storage?

CodeDredd commented 2 years ago

thanks for finding that going to look into it after finishing all tests which i refactored all from vuex-orm-next tests and i am 90% done. so much work ^^

CodeDredd commented 2 years ago

@tintin10q sooooo lets see....after adding 182 tests my head is already in standby mode ^^

tintin10q commented 2 years ago

Woah 182 test what an amazing effort 🤩

tintin10q commented 2 years ago

But I bet it was super satisfying when they all to passed 😄

182 passed 🍕

CodeDredd commented 2 years ago

yes it was....but most work was already done by Kia King and the contributers. I just made them pinia-orm compatible and migrated to vitest.

CodeDredd commented 2 years ago

@tintin10q i tested your code. And it seems to work after i fixed the double quote marks:

<template>
  <button @click="todo.save({text:'Fix TS support', name:'TS Todo'})">Add todo</button>
  <button @click="todo.flush()">Clear Todos</button>
  <span>{{all_todo_text}}</span>
</template>

<script setup lang="ts">
import { useRepo } from 'pinia-orm'
import Todo from "./models/ToDo";

const todo = useRepo(Todo);
const all_todo_text = computed(() => todo.all().map((t: Todo) => t.text));

</script>
CodeDredd commented 2 years ago

I close this for now....if you need any help just write again