dynamodb-toolbox icon indicating copy to clipboard operation
dynamodb-toolbox copied to clipboard

Dynamically generated types for output of Entity.parse()

Open willsmanley opened this issue 3 years ago • 4 comments

This idea was inspired by how Redux Toolkit allows you to define types from your reducers without having to write everything twice (see: https://redux-toolkit.js.org/tutorials/advanced-tutorial, search page for "ReturnType")

The same strategy could be applied to creating an Entity and then defining a type for the output of YourEntity.parse():

const YourEntity = new Entity({
	name: 'yourEntity',
	table: Table,
	attributes: {
		something: {
			partitionKey: true,
                         type: 'string',
		},
		somethingelse: {
			sortKey: true,
                         type: 'string',
		},
                ...
	},
});

// Better usage
type YourEntityAttributes = ReturnType<typeof YourEntity.parse>;

// WET usage
interface YourEntityAttributes {
   something: string,
   somethingelse: string,
   ...
}

I'm not sure if the current implementation of parse() is understandable by TypeScript to the same level of accuracy as it is in Redux Toolkit, but I wanted to flag it as a very helpful way to avoid re-writing types and as a goal for parse() to make the exact attribute output evident for the TypeScript engine.

Perhaps in the meantime this typescript strategy could be included in the readme as it took me a while to figure out how to do this.

willsmanley avatar Jan 15 '21 10:01 willsmanley

Thanks @famouspotatoes. I have been exploring ways to infer types from the entity definitions rather than requiring it separately. I will look into the redux stuff and see if there is anything I can use.

jeremydaly avatar Jan 15 '21 15:01 jeremydaly

Nice 😀 Have you tried this with the library, @famouspotatoes? What is your result for this? It may "just work"...

darbio avatar Jan 15 '21 20:01 darbio

@darbio I have and it works to the extent that it does not throw any typescript errors, but not to the degree of accuracy where typescript/IDE can infer the exact attributes and types.

I'm not sure how redux toolkit does it under the hood but i can say that it is very cool and makes this abstraction stuff a lot more effective.

willsmanley avatar Jan 16 '21 00:01 willsmanley

Ah yes - I see. You have to have the method return T. At the moment it returns:

// Return the entity
  return Object.assign({
    name,
    schema: parseEntityAttributes(attributes,track), // removed nested attribute?
    defaults: track.defaults,
    required: track.required,
    linked: track.linked,
    autoExecute,
    autoParse,
    _etAlias: typeAlias 
  },
  table ? { table } : {}
  ) // end mapping object

Making parseEntity generic could make this work.

Does this already work for the generic constructor of entity? (Entity<T>)

darbio avatar Jan 16 '21 05:01 darbio

Hey @willsmanley, thanks for opening this issue and sorry for the delayed response.

This was added in v0.4, feel free to install the latest version of the library to get the TS inference.

naorpeled avatar Nov 30 '22 12:11 naorpeled