Chad
Chad

Reputation: 2071

Filtering out objects with null or undefined properties

I am using the AWS SDK and it looks like a lot of it's objects have members that can be undefined. Example below is for S3.Object

  export interface Object {
    /**
     * 
     */
    Key?: ObjectKey;
    /**
     * 
     */
    LastModified?: LastModified;
    /**
     * 
     */
    ETag?: ETag;
    /**
     * 
     */
    Size?: Size;
    /**
     * The class of storage used to store the object.
     */
    StorageClass?: ObjectStorageClass;
    /**
     * 
     */
    Owner?: Owner;
  }

So when processing a list of these objects, I always have to check at the top of the function if the member is not undefined.

objects.map(async (object) => {
    if(object.Key) { 
        return
    }
    ...
}

I tried the following but didn't work:

const objects = objects.filter(object => object.Key)

but the type of objects is still S3.Object thus making Key still string|undefined.

I also tried:

const objects: {Key: string}[] = objects.filter(object => object.Key)

But I am getting the following error:

Type 'Object[]' is not assignable to type '{ Key: string; }[]'.
  Type 'Object' is not assignable to type '{ Key: string; }'.
    Types of property 'Key' are incompatible.
      Type 'string | undefined' is not assignable to type 'string'.
        Type 'undefined' is not assignable to type 'string'

Is there a way to filter the objects first by this property? I want to remove undefined checking for this property whenever processing objects

Upvotes: 1

Views: 1229

Answers (1)

Frank Bessou
Frank Bessou

Reputation: 652

You can use a type guard for that:

interface S3Object {
    Key?: string;
}

interface MyObject {
    Key: string;
}

function isValidObject(obj: S3Object): obj is MyObject {
    return obj.Key !== undefined;
}

let objs1: S3Object[] = [{Key: ''}, {Key: 'test'}, {}, {}];

let objs2: MyObject[] = objs1.filter(isValidObject);

console.log(objs2);

Here isValidObject can be used in filter to make the compiler know that filtered items are of type MyObject.

Of course you can remove the MyObject interface and replace it by {Key: string}

Documentation of this feature.

Upvotes: 2

Related Questions