ChuckJonas / ts-force

A Salesforce REST Client written in Typescript for Typescript
88 stars 21 forks source link

allow using `ts-force` and `ts-force-gen` in a project with `"strict"` mode #94

Closed bengry closed 3 years ago

bengry commented 4 years ago

Currently when using ts-force-gen it generates class properties that are not initialized in a way that's [currently] statically analyzable by the TS compiler.

In addition, the reference property of SFieldProperties is sometimes generated as undefined.

This is fine in projects that don't use "strictNullChecks": true (or "strict": true, which includes it).

This RP aims to fix issues and allow using strict mode in TS projects that want to use ts-force, without needing to further exit their generated files by ts-gen-force or by patching ts-force.

The current alternative we use is to patch ts-force using patch-package:

diff --git a/node_modules/ts-force/build/rest/sObjectDecorators.d.ts b/node_modules/ts-force/build/rest/sObjectDecorators.d.ts
index d376fc6..a6c6ea9 100644
--- a/node_modules/ts-force/build/rest/sObjectDecorators.d.ts
+++ b/node_modules/ts-force/build/rest/sObjectDecorators.d.ts
@@ -29,7 +29,7 @@ export declare class SFieldProperties {
     apiName: string;
     updateable: boolean;
     createable: boolean;
-    reference: () => {
+    reference?: () => {
         new (): RestObject;
     };
     required: boolean;

and to add @ts-ignore on all property initializations in generated classes. e.g.:

export class Account {
  ...
  constructor(fields?: AccountFields, restInstance?: Rest) {
    super("Account", restInstance);
    // @ts-ignore
    this.contacts = void 0;

    ...
  }
}
ChuckJonas commented 4 years ago

Would it make sense if the code generation also just added the // @ts-ignore comment as well?

this.contacts = void 0; is required for the SFieldProps attribute to be readable when the field is not set (or at least it was when I wrote this).

bengry commented 4 years ago

Would it make sense if the code generation also just added the // @ts-ignore comment as well?

this.contacts = void 0; is required for the SFieldProps attribute to be readable when the field is not set (or at least it was when I wrote this).

Not sure that's needed really, since both ways (1. putting a @ts-ignore, 2. putting an ! after the class member declaration) achieves the same thing. IMO the latter is less extreme - since a @ts-ignore ignores TS errors for the entire line, putting an ! is just telling TS "this field will be initialized, don't worry about checking for that).

Putting ! on the field declarations is also a common practice in other, similar scenarios - like TypeORM entity declarations or NestJS DTO objects.

I didn't remove the this.contacts = void 0;, those are fine to be kept, as long as you put the ! on the field declarations.

ChuckJonas commented 3 years ago

The generated types should be "strict" compatible in the v3 RC now.