0

I am trying to change a private field from a method of the same class with immer.js But in this case, I need to access not to this, but to the draft instance of same class. This causes an error.

import produce from "immer";

export class Test {
    private foo: number = 0;
    bar(foo: number): Test {
        return produce<Test>(this, draft => {
            draft.foo = foo;    // <- TS2339: Property 'foo' does not exist on type '{ bar: (foo: number) => Test; }'.
        })
    }
}

Is there some way to use immer.js without turning fields into public?

Del Oracle
  • 63
  • 1
  • 3

2 Answers2

0

You can cast draft to any and then access foo untyped.

import produce from "immer";

export class Test {
    private foo: number = 0;
    bar(foo: number): Test {
        return produce<Test>(this, draft => {
            (draft as any).foo = foo;
        })
    }
}
Rain336
  • 1,450
  • 14
  • 21
  • Yes, it's solution... But it actually takes away all benefits of typescript. Maybe there are other solutions? – Del Oracle Oct 24 '19 at 10:42
  • you could also try to use `Test & { foo: number }` as type. – Rain336 Oct 24 '19 at 10:46
  • This causes TS2546: Property 'foo' has conflicting declarations and is inaccessible in type 'Test & { foo: number; }'. I can cast to ```Omit & { foo: number }``` but it's very ugly – Del Oracle Oct 24 '19 at 10:55
0

I came to the same problem and I think I got a better solution:

import produce from "immer";

export class Test {
    private foo: number = 0;
    bar(foo: number): Test {
        return produce(this, (draft: this) => {
            draft.foo = foo;
        })
    }
}

That seems to satisfy TypeScript with all the strong types benefits :)