0

Why does this piece of code fail?

/**
 * Write the provided contents to a file in the specified directory.
 */
public writeFile(subPath: string, contents: string | Object) {
  // stringify the contents if they are not already
  if (contents && typeof contents === 'object') contents = JSON.stringify(contents);

  this.file.writeFile(this.path, subPath, contents);
}

With the following error:

Argument of type 'string | Object' is not assignable to parameter of type 'string | ArrayBuffer | Blob'. Type 'Object' is not assignable to type 'string | ArrayBuffer | Blob'. The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead? Type 'Object' is not assignable to type 'Blob'. The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead? Property 'size' is missing in type 'Object'.

I understand writeFile(...); does not accept an Object for its third property, text. But, I have stringified it in the if statement...

The signature to writeFile(...); looks like this:

/** Write a new file to the desired location.
 *
 * @param {string} path Base FileSystem. Please refer to the iOS and Android filesystems above
 * @param {string} fileName path relative to base path
 * @param {string | Blob} text content or blob to write
 * @param {IWriteOptions} options replace file if set to true. See WriteOptions for more information.
 * @returns {Promise<any>} Returns a Promise that resolves to updated file entry or rejects with an error.
 */
writeFile(path: string, fileName: string, text: string | Blob | ArrayBuffer, options?: IWriteOptions): Promise<any>;

The error asks if I meant to use any - I did not, since I want stricter control as I'd like to control what can and cannot be passed to this function.

How do I overcome this?

1 Answer 1

2

Use another variable for the stringified contents.

Typescript can't know in compile time will your contents be parsed into the string or will stay as object.

Compiler don't see what are you doing in the if statement. It sees only that the type of contents is string | object, so there may be an object and when you pass it to the writeFile function parameter, which is only string, it complains you about it.

Look that I have called toString() on the contents to assure compiler that 2 sides of my ternary operator returns string.

public writeFile(subPath: string, contents: string | Object) {

      if(!contents) {
         contents = '';
      }

      const contentsAsString: string = typeof contents === 'object' ? 
                               JSON.stringify(contents) : contents.toString();      

      this.file.writeFile(this.path, subPath, contentsAsString);
}
Sign up to request clarification or add additional context in comments.

2 Comments

The type guard works on the ternary operator so long as you can remove the null check: const contentsAsString: string = typeof contents === 'object' ? JSON.stringify(contents) : contents;
The toString()' won't be called in that case as null` is an Object, instead you would get 'null' in the file. Best would be to compile with strict null checks and then you never get a null, otherwise a simple if (!contents) contents = ''; at the top of the function would make it safe.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.