dynamodb-toolbox
dynamodb-toolbox copied to clipboard
Sub object list type Typescript error
So I get a type error when trying to have a list of sub-objects on my primary object type.
This is my setup.
export interface MyObject {
id: string
created: string
objects: MySubObjectType[]
}
export interface MySubObjectType {
foo: string
}
myEntity = new Entity<MyObject>({
name: 'MyObjectType'
attributes: {
id: { partitionKey: true }
created {sortKey: true}
objects: {type: 'list'}
}
})
I get an error Unable to apply to Schema type
Currently schema type looks like this: declare type SchemaType = string | number | boolean | { [key: string]: SchemaType } | SchemaType[];
I think the issue is this part of the SchemaType type ... { [key: string]: SchemaType }
, Typescript does not seem to like an object with a {[key: string]: string | ...otherTypes }
which is effectively what SchemaType
is, see this issue on stack overflow.
The fix based on that stack overflow post is to just have {[key: string]: any}, you still seem to get the correct type hinting with this setup.
Happy to do a PR with this fix, unless you maybe have some more typescript fu than me, and can wrangle something a little better.
Copy past this into typescript playground to play around yourself
export interface MyObject {
id: string
created: string
objects: MySubObjectType[]
}
export interface MySubObjectType {
foo: string
}
// existing types (do not work)
declare type SchemaType = string | number | boolean | { [key: string]: SchemaType } | SchemaType[];
class Entity<Schema extends {[key in keyof Schema]: SchemaType}> {
foo: Schema
constructor(schema: Schema) {
this.foo = schema
}
}
const myEntityInstance: Entity<MyObject> = new Entity({id: '1', created: 'created', objects: [{foo: 'bar'}]})
myEntityInstance.foo.objects[0].foo
// updated types (works)
declare type NewSchemaType = string | number | boolean | { [key: string]: any } | SchemaType[];
class EntityTwo<Schema extends {[key in keyof Schema]: NewSchemaType}> {
foo: Schema
constructor(schema: Schema) {
this.foo = schema
}
}
const myEntityInstanceTwo: EntityTwo<MyObject> = new EntityTwo({id: '1', created: 'created', objects: [{foo: 'bar'}]})
myEntityInstanceTwo.foo.objects[0].foo
@jeremydaly any update on this? I would like to have the definition like this
export declare type SchemaType = string | number | boolean | null | undefined | Record<string, SchemaType> | SchemaType[];
At least include undefined
in the SchemaType
?
This would allow to write something like:
export interface MyObject {
id: string
name?: string
}
instead of:
export interface MyObject {
id: string
name: string | null
}
Is there a suitable workaround for this? I am currently having to type my object as any:
interface IQuestionnaire {
questions: IQuestionnaireQuestion[] //having to change this to any
}
Hey @vespertilian, with the latest version you can achieve what you're looking for.
export interface MyObject {
id: string;
created: string;
objects: MySubObjectType[];
}
export interface MySubObjectType {
foo: string;
}
const myEntity = new Entity<'MyEntityName', MyObject>({
name: 'MyEntityName',
attributes: {
id: { partitionKey: true },
created: {sortKey: true},
objects: {type: 'list'},
}
})
Is there a suitable workaround for this? I am currently having to type my object as any:
interface IQuestionnaire { questions: IQuestionnaireQuestion[] //having to change this to any }
Let me know if the solution I've mentioned above doesn't work for you, it should work for you as well 🙏
Hi, thanks so much for the reply! I will upgrade to the latest version and try this out.
Hi, thanks so much for the reply! I will upgrade to the latest version and try this out.
Awesome, sounds good, let me know if you need anything!
I'll be closing this issue for now, @shesupplypi feel free to ping me if you need anything 😎
@naorpeled Quick one related to this, when I use types like this I'm getting an error when I add the table
property as per the docs:
const DocumentClient = new DynamoDB.DocumentClient({
convertEmptyValues: false,
...options,
});
const MyTable = new Table({
name: config.TABLE_NAME,
partitionKey: "sub",
DocumentClient
});
export interface NotificationType {
id: string;
notificationTimes: {
time: string;
hasBeenSent: boolean;
}[];
}
const NotificationORM = new Entity<'notification', NotificationType>({
name: "notification",
attributes: {
id: { partitionKey: true },
notificationTimes: {type: 'list'},
},
// Assign it to our table
table: MyTable
} as const)
Types of property 'table' are incompatible. Type 'Table<string, "sub", Key>' is not assignable to type 'undefined'
Do I need to add some types in the table creation as well?
@naorpeled Quick one related to this, when I use types like this I'm getting an error when I add the
table
property as per the docs:const DocumentClient = new DynamoDB.DocumentClient({ convertEmptyValues: false, ...options, }); const MyTable = new Table({ name: config.TABLE_NAME, partitionKey: "sub", DocumentClient }); export interface NotificationType { id: string; notificationTimes: { time: string; hasBeenSent: boolean; }[]; } const NotificationORM = new Entity<'notification', NotificationType>({ name: "notification", attributes: { id: { partitionKey: true }, notificationTimes: {type: 'list'}, }, // Assign it to our table table: MyTable } as const)
Types of property 'table' are incompatible. Type 'Table<string, "sub", Key>' is not assignable to type 'undefined'
Do I need to add some types in the table creation as well?
You need to remove the generics from the entity. If you want to use the type of the entity you can do the following
type Notification = EntityItem<typeof NotificationORM>
let me know if you have any further questions 🙏