sebelga / gstore-node

Google Datastore Entities Modeling for Node.js

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Creating entities that have required properties with default values in TypeScript

Maher4Ever opened this issue · comments

Hello,

Consider the following definition of a User entity:

interface UserType {
  name: string;
  status: string;
}

type UserEntity = Entity<UserType>

const schema = new Schema<UserType>({
  name: {
    type: String
  },
  status: {
    type: String,
    values: ['unverified', 'verified'],
    default: 'unverified',
    write: false,
    required: true
  },
})

const User = gstore.model('User', schema)

If you now try to create a user without passing a status then the compiler complains:

const user = new User({ name: 'John' })
/*
Argument of type '{ name: string; }' is not assignable to parameter of type 'EntityData<UserType>'.
  Property 'status' is missing in type '{ name: string; }' but required in type 'EntityData<UserType>'.ts(2345)
*/

According to the documentation this can be solved by making the status property optional in the interface:

interface UserType {
  name: string;
  status?: string;
}

const user = new User({ name: 'John' }) // OK

However, now I'm forced to tell the compiler everywhere the status property is used that it can't be undefined:

const status: string = user.status // Type 'string | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type 'string'.ts(2322)

// The following works of course but it's annoying
const status: string = user.status!

Is there a better way to handle this use case?

Hello,

As far as I know, this is how it should be. If you create a user with

const user = new User({ name: 'John' })

That user does not have a status, it this then undefined. If your logic updates the status, you are the only one that knows it for sure and that's why Typescript lets you add an ! behind.

I can see that. Would it be possible to add a factory method to models that takes a Partial entity type?