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

Typescript issue while declaring entity

Open rdzidziguri opened this issue 2 years ago • 9 comments

The inferred type of 'Tenant' cannot be named without a reference to '../../../../node_modules/dynamodb-toolbox/dist/esm/classes/Entity/types'. This is likely not portable. A type annotation is necessary.

Getting the following TS issue while implementing Entity declaration

import { Entity, EntityItem } from 'dynamodb-toolbox'
import { tableDefinition } from '../table'

export const Tenant = new Entity({
    name: 'tenant',
    attributes: {
     ... //removed for clarity 
    },
    table: tableDefinition,
} as const)

export type TenantEntity = EntityItem<typeof Tenant>

version used - 0.9.1 typescript version - 5.2.2

rdzidziguri avatar Nov 28 '23 13:11 rdzidziguri

I found it need to set"strict": true in tsconfig.json to make it work.

IIIOTL avatar Nov 30 '23 14:11 IIIOTL

Unfortunately, it did not help; I still see the same error.

rdzidziguri avatar Dec 02 '23 00:12 rdzidziguri

I found it need to set"strict": true in tsconfig.json to make it work.

Worked for me thanks @IIIOTL

vespertilian avatar Dec 20 '23 23:12 vespertilian

@IIIOTL setting strict caused other issue for me. Maybe try to use InferEntityItem instead of EntityItem this seemed to also work to give me the types.

Also I just noticed that I have a slightly different issue where the type is returned as undefined.

vespertilian avatar Dec 21 '23 11:12 vespertilian

Very strange but even using. InferEntityItem gives the same error.

{
	"resource": "/serverless-dynamodb-client/src/entities/entity.ts",
	"owner": "typescript",
	"code": "2742",
	"severity": 8,
	"message": "The inferred type of 'Entity' cannot be named without a reference to '../../../../node_modules/dynamodb-toolbox/dist/esm/classes/Entity/types'. This is likely not portable. A type annotation is necessary.",
	"source": "ts"
}

UPDATE: The only way I could make this problem go away inside VS code was to modify that project tsconfig and add

{
    "declaration": false,
    "declarationMap": false
}

under compilerOptions

While this makes the problem in VS Code go away, it is extraordinary and now the bigger question is why it ever worked :)

rdzidziguri avatar Jan 10 '24 01:01 rdzidziguri

The problem is that Typescript requests the dev to write a return type when the inferred type would reference something that isn't exported to the outside of dynamodb-toolbox. In this case, it is a hidden type inside classes/Entity/types.

As a quite cumbersome workaround, I solved it by not exporting the entities themselves but exporting the configuration that I use to build the entities.

Example: From one module I export the following:

export const userEntityAttributes = {
    name: 'User',
    timestamps: true,
    createdAlias: 'createdAt',
    modifiedAlias: 'updatedAt',

    attributes: {
        id: { type: 'string' },

        pk: {
            type: 'string',
            partitionKey: true,
            default: (data: { id: string }) => `USER#${data.id}`,
        },
        sk: {
            type: 'string',
            sortKey: true,
            default: (data: { id: string }) => `#PROFILE#${data.id}`,
        },

        name: { type: 'string', required: true },
        email: { type: 'string', required: true },
        description: { type: 'string', required: false, default: () => '' },
    },
} as const;

export const APPLICATION_TABLE_NAME = 'my-app-table';
export const PARTITION_KEY_NAME = 'pk';
export const SORT_KEY_NAME = 'sk';

export const documentClientConfig = {
    marshallOptions: {
        // Specify your client options as usual
        convertEmptyValues: false,
    },
};

From another module, I import that and do the rest:

import {
    APPLICATION_TABLE_NAME,
    documentClientConfig,
    PARTITION_KEY_NAME,
    SORT_KEY_NAME,
    userEntityAttributes,
} from '@myapp/crud';

import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
import { Entity, Table } from 'dynamodb-toolbox';

function awesomeLogicUsingDynamo() {
    const DocumentClient = DynamoDBDocumentClient.from(new DynamoDBClient(), documentClientConfig);

    const applicationTable = new Table({
        name: APPLICATION_TABLE_NAME,

        partitionKey: PARTITION_KEY_NAME,
        sortKey: SORT_KEY_NAME,

        DocumentClient,
    });

    const UserEntity = new Entity({ ...userEntityAttributes, table: applicationTable });

    // ...now UserEntity is ready to rock...
}

mattes3 avatar Jan 14 '24 13:01 mattes3

I have also encountered this issue (Typescript error: TS2742) while converting a data access module I have to Typescript. This module is an NPM dependency in other repos, so I need the typescript definitions files.

My grasp on Typescript is a little tenuous, But from all that I could read and gather from similar issues and actions taken in other libraries, it seems that exporting the additional types is necessary.

As far as I can see the only additional type needed in the end was ParseAttributes,

I have added a pull request https://github.com/jeremydaly/dynamodb-toolbox/pull/655 that fixes this for me, @rdzidziguri can you test to see if that solves for you too?

whahoo avatar Jan 16 '24 05:01 whahoo

@whahoo, we are happy with our fix for now, but the fix you described could also work. @mattes3 While the solution is a workaround, the fact that there is no type of safety on userEntityAttributes sounds a bit scary.

rdzidziguri avatar Jan 24 '24 22:01 rdzidziguri

@rdzidziguri You said "we are happy with our fix for now" – does that mean that there is already a fix? This would be great! In which version on NPM is it?

mattes3 avatar Jan 25 '24 08:01 mattes3

Very strange but even using. InferEntityItem gives the same error.

{
	"resource": "/serverless-dynamodb-client/src/entities/entity.ts",
	"owner": "typescript",
	"code": "2742",
	"severity": 8,
	"message": "The inferred type of 'Entity' cannot be named without a reference to '../../../../node_modules/dynamodb-toolbox/dist/esm/classes/Entity/types'. This is likely not portable. A type annotation is necessary.",
	"source": "ts"
}

UPDATE: The only way I could make this problem go away inside VS code was to modify that project tsconfig and add

{
    "declaration": false,
    "declarationMap": false
}

under compilerOptions

While this makes the problem in VS Code go away, it is extraordinary and now the bigger question is why it ever worked :)

The fix is the one I described here actually it is more of a workaround for us.

rdzidziguri avatar Feb 10 '24 23:02 rdzidziguri