question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Different behaviour than tsc+node when using class-transformer

See original GitHub issue

First of all great project, I have really been enjoying using it. 😄 I found a weird issue when doing some exploration testing on class-transformer.

I’m using class-transformer to convert a plain object to a classed instance. Like this:

test("This should work", () => {
  class Weapon {
    constructor(public model: string,
                public range: number) { }
  }

  class User {
    public id: number;
    public name: string;

    @Type(() => Weapon)
    public weapons: Map<string, Weapon>;
  }

  const plainUser = {
    id: 1,
    name: "Max Pain",
    weapons: { firstWeapon: { model: "knife",  range: 1 } },
  };

  const classedUser = plainToClass(User, plainUser);
  expect(classedUser).toBeInstanceOf(User);
  expect(classedUser.weapons).toBeInstanceOf(Map);
});

Issue

class-transformer should transform the nested object plainUser.weapons from object to Map<string, Weapon>. The issue is that when I execute that test it fails, instead of transforming to Map<string, Weapon I get Weapon. But when I run it regularly (tsc then node) it works.

In test:

classedUser is instance of User? true
classedUser.weapons is instance of Map? false
classedUser.weapons is instance of Weapon? true
 FAIL  ./index.test.ts
  ● This should work

    expect(value).toBeInstanceOf(constructor)
    
    Expected value to be an instance of:
      "Map"
    Received:
      {"firstWeapon": {"model": "knife", "range": 1}, "model": undefined, "range": undefined, "secondWeapon": {"model": "eagle", "range": 200}, "thirdWeapon": {"model": "ak-47", "range": 800}}
    Constructor:
      "Weapon"
      
      at Object.<anonymous> (index.test.ts:50:31)
          at Promise (<anonymous>)
          at <anonymous>
      at process._tickCallback (internal/process/next_tick.js:169:7)

  ✕ This should work (263ms)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        1.915s
Ran all test suites.

Expected behavior

expect(classedUser.weapons).toBeInstanceOf(Map); // Should pass

In node:

classedUser is instance of User? true
classedUser.weapons is instance of Map? true
classedUser.weapons is instance of Weapon? false

Repo

  • npm start runs tsc + node (expected behaviour)
  • npm test runs jest (issue)
  • I included the compiled js
node v8.1.3
jest v20.0.4
ts-jest v20.0.6
typescript v2.4.1

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:17 (8 by maintainers)

github_iconTop GitHub Comments

2reactions
DorianGreycommented, Aug 4, 2017

Note that although it seems different, program.emit is synchronous - the callback is just called for every file to write. In fact, transpileModule is using it internally: https://github.com/Microsoft/TypeScript/blob/4b3e661aaa69e53b6a5992c76f2232c9f5dace10/src/services/transpile.ts#L100 Generated code is extracted with the writeFile callback of the compilerHost. For the purpose mentioned here, it would be required to copy most of the transpileModule implementation, excluding some of the option reset steps (I’m not sure which ones - should be tested). It is intended that some of these options are removed, to avoid problems with the single file perspective of transpileModule. I’m not sure if this may work in a more complex project.

1reaction
floriansimon1commented, Feb 6, 2018

The way files get transpiled makes all libraries that use design:type untestable with ts-jest, as the wrong info gets returned when querying the design:type metadata. There is no possible workaround.

I’d like to state my disagreement with the classification of this problem as a TS bug. TS puts the tools at your disposal (see @thevtm’s work, or the language services API), but you’re not using them. There is a possibility to make this work, but it’s not yet done, for reasons I can understand. I also understand that you don’t owe the community anything, but I’d like to make a suggestion.

Maybe it’d be interesting to put a note in the README to let your users know that libraries like typegoose or class-transformer that rely on proper reflection won’t work with ts-jest? I can do it if it’s fine for you. At least, this would allow your users to not lose time trying to make ts-jest work when it clearly cannot, whatever the reason may be.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Flexible entities with class-transformer | Vue.js Developers
Class-transformer gives us declarative functionality for describing models that We should transform before using. Also one model may be as property of another...
Read more >
Different behaviour with Mocha between `pnpm ln -g <pkg ...
The repo I am working on is a private one, so I can only post some excerp. For testing, we use Mocha's testname.spec.ts...
Read more >
class-transformer - npm
Start using class-transformer in your project by running `npm i class-transformer`. There are 3187 other projects in the npm registry using ...
Read more >
How to set up TypeScript
Then you use a dependency manager like npm, yarn or pnpm to download TypeScript into your project. npm install typescript --save-dev npm yarn...
Read more >
Serialization | NestJS - A progressive Node.js framework
In doing so, it can apply rules expressed by class-transformer decorators on an entity/DTO class, as described below. Exclude properties#. Let's assume that...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found