0

I've got this class:

export class AccountApprovedColumnFilter {

    public showRowNumber: boolean = true;
    public showImage: boolean = true;
    public showProduct: boolean = true;
    public showCategory: boolean = true;
    public showGender: boolean = true;
    public showSupplyingAccount: boolean = true;
    public showSalesOrder: boolean = true;
    public showRequestedUnits: boolean = true;
    public showApprovedUnits: boolean = true;
    public showSizeDetails: boolean = true;
    public showSubmit: boolean = true;

    public reset(): void {
        for (let key in this) {
            if (this.hasOwnProperty(key)) {
                this[key] = true;
            }
        }
    }
}

But Visual Studio complains about this line:

this[key] = true;

Type 'true' is not assignable to type 'this[keyof this]'.

How do I cast this properly?

Amit Chigadani
  • 28,482
  • 13
  • 80
  • 98
Willem de Jong
  • 905
  • 2
  • 15
  • 31

1 Answers1

1

The TypeScript compiler is inferring the type of key to be keyof this, and for whatever reason, it isn't able to statically verify that all the possible values of this[keyof this] can be set to a boolean value.

You can get around this by providing an explicit type in the function signature:

public reset(this: AccountApprovedColumnFilter): void {
   ...
}

This will get erased in the final output (i.e. it doesn't add an extra parameter to your method).


Note that this feature wasn't added until TypeScript 2.0 - if you're stuck on an older version for whatever reason, another workaround would be to cast this in your loop:

public reset(): void {
    for (let key in this as AccountApprovedColumnFilter) {
         if (this.hasOwnProperty(key)) {
             this[key] = true;
         }
    }
}

Worst case scenario, you can create a temporary variable and give that an explicit type:

public reset(): void {
    const self: AccountApprovedColumnFilter = this;
    for (let key in self) {
         if (self.hasOwnProperty(key)) {
             self[key] = true;
         }
    }
}
Joe Clay
  • 33,401
  • 4
  • 85
  • 85
  • I forgot to mention that the code actually works, it is just Visual Studio that is complaining. – Willem de Jong May 16 '18 at 12:44
  • @WillemdeJong: Hm, it works in the [TypeScript playground](https://www.typescriptlang.org/play/) - which version of TypeScript are you using? If it's not a relatively recent one, you might not be able to do this. – Joe Clay May 16 '18 at 12:48
  • @WillemdeJong: I've added some workarounds that should work if your TypeScript compiler doesn't support explicit `this` typing. Also, your code working even though VS is complaining isn't entirely unexpected - TypeScript almost always outputs code even when type errors are found, precisely because there's scenarios like this where you know your code is right but you just haven't figured out how to get the type system to accept it yet :) – Joe Clay May 16 '18 at 12:55
  • Well, of course the code works. Even if it happened, Javascript wouldn't complain about a property changing type. In this special case all properties are of boolean type. However, Typescript does not use this information. The provided workaround works, because `this[key]` is treated as of `any` type. The whole idea in the question is just bad design. Either reassign all properties manually in reset or use a map (`{[key: string]: boolean}`) for your booleans. If you prefer keeping it, rather use `( this[key]) = true` so it's more verbose that you cheat there. – Neonit May 16 '18 at 13:29
  • I reassigned the properties individually now, which solves the issue. Thanks anyways. – Willem de Jong May 17 '18 at 13:31