Home > Net >  Best way to handle uninitialised class values in TypeScript - Object is possibly 'null'
Best way to handle uninitialised class values in TypeScript - Object is possibly 'null'

Time:02-26

I've created a wrapper class for S3 operations but when I compile using the TypeScript complier I get the following error:

lib/Store.ts:20:15 - error TS2531: Object is possibly 'null'.

20         await this.store.upload({

I'm new to TypeScript but I understand TypeScript is doing it's job here and preventing the possibility that await this.store.upload() could run while this.store is null. What's the correct way for dealing with this type of situation where a class value might not yet be initialised?

My wrapper class:

import S3 from 'aws-sdk/clients/s3';

export class Store {
    storeName: string;
    store: S3 | null;
    initialised: boolean;
   
    constructor(storeName: string) {
        this.storeName = storeName;
        this.store = new S3();
        this.initialised = false;
    }
    
    _init(): void {
        this.store = new S3();
    }

    async _writeToStore(data: object, path: string): Promise<void>  {
        if (!this.initialised) this._init();
        await this.store.upload({
            Bucket: this.storeName,
            Key: path,
            Body: data
        }).promise();
    }
}

I've always tried to avoid creating new instances of classes in the constructor because it's awkward to mock. Maybe passing a new class instance into the constructor is the best approach?

CodePudding user response:

You can try
{
...
"strictNullChecks": true,
"strictPropertyInitialization": true,
...
}

"strictNullChecks" tells the compiler to watch for any declared variables that evaluate to null or undefined and raise on error on at compiler time (https://www.typescriptlang.org/tsconfig#strictNullChecks) "strictPropertyInitialization" tells the compiler to raise an error 'when a class property was declared but not set in the constructor'. (https://www.typescriptlang.org/tsconfig#strictPropertyInitialization)

CodePudding user response:

Typescript is giving you that error because you have strictNullChecks enabled and your property store has null as a possible type.

You can do any of these options

Option 1 - Remove null type

You can probably drop the null type on store, since you are setting the value of that property on your constructor, and nothing on your code sets it to null:

  store: S3;

Option 2 - Add non-null assertion operator

Alternatively, if this.store is never going to be null when you execute this.store.upload({...}), then you can add a non-null assertion operator (!) like this:

  this.store!.upload({...})

That will tell Typescript to stop giving the error. Note that this doesn’t change the runtime behavior of your code, so it's important to only use ! when you know that the value can't be null or undefined.

Option 3 - Check store for null value right before

You can explicitly check this.store for null value right before calling this.store.upload(). But this call must be done within the same method, like this:

   if (!this.store) {
      this.store = new S3();
   }
   await this.store.upload({...});

This won't work:

   if (!this.store) {
      this._init();
   }
   await this.store.upload({...});

Conclusion

Personally, I would go with option 1. I'm assuming that your reason for writing a wrapper for S3 is so that your consumers never have to instantiate and work directly with an S3 object and instead instantiate and work with your wrapper class/object.

  • Related