Search code examples
typescriptdecoratorcode-splittingfirst-class

What type has the `class` created by a `function`?


The goal is to do a code splitting in my TypeScript code.

I use (experimental) decorators to support ORM-like data mapping from models to persistent storage. One of types needs to have a decorator parameterized with a name of a table which will store the entities of that type. In order to do a code splitting I have extracted domain model to a separate file (entity-model.ts):

/* I am using dynamodb-data-mapper */
import { 
  table,
  hashKey,
  attribute
} from '@aws/dynamodb-data-mapper-annotations'

export class Entity {
  /* attributes */
}

/* this entity is parameterized with name of the table
   where data will be stored */
export function entityGroupClassFactory(tableName: string)/*: ???*/ {
  @table(tableName)
  class EntityGroup {
    @hashKey()
    id: string,

    @attribute({ memberType: embed(Entity) })
    children: Entity[]

  }
  return Entity
}

When I use this file in the following way:

import { entityGroupClassFactory, Entity } from './entity-model.ts'
import { DataMapper } from '@aws/dynamodb-data-mapper';

const mapper : DataMapper = createDataMapper()
const tableName : string = deterineTableName()

const EntityGroup = entityGroupClassFactory(tableName)

/* eventually I do */

let entityGroup = mapper.get(/*...*/)

/* and at some point I am trying to do this: */

function handleEntityGroup(entityGroup: EntityGroup) {
  /* ... */
}

/* or this: */

async function fetchEntityGroup(): Promise<EntityGroup> {
  const entityGroup = /* ... */
  return entityGroup
}

For the both functions (handleEntityGroup and fetchEntityGroup) TypeScript reports the following error:

[ts] Cannot find name 'EntityGroup'. [2304]

I am not sure about the correctness of such approach and I will look for other options to do the code splitting. But as a beginner in this area I would like to get answer to question: what is EntityGroup in this example code?

Thank you.


Solution

  • When you declare a class, you get both a value (representing the class constructor) and a type (representing the instance type of the class) with the class name.

    When you are using a function to return a class, and putting it in the const you are basically only getting the value, the instance type has no reason to be created.

    Fortunately you can use InstanceType<typeof EntityGroup> to get the instance type associated with the constructor EntityGroup.

    const EntityGroup = entityGroupClassFactory(tableName)
    type EntityGroup = InstanceType<typeof EntityGroup>