zhm
zhm

Reputation: 3641

Property does not exist on a function's return value of multiple types

I'm using typescript to write NodeJS program.

In this program, I import a node module called ts-md5, in which there is a function hashStr(), it could return a value of string or Int32Array.

I need to do things like this in my program:

Md5.hashStr(str).toUpperCase();

However, the compiler complains error:

error TS2339: Property 'toUpperCase' does not exist on type 'string | Int32Array'.

The program runs successfully. Because it always returns string during runtime. But I want to know if there is a way to get rid of this annoying error?

Upvotes: 2

Views: 1684

Answers (2)

artem
artem

Reputation: 51619

hashStr is declared in ts-md5 typings as

static hashStr(str: string, raw?: boolean): string | Int32Array;

Looking at the implementation, is seems that it returns Int32Array when raw is true, and returns string otherwise.

Given that declaration, you can't do much better than use type assertion:

let hash = (Md5.hashStr(str) as string).toUpperCase()

The proper way to express that return type is dependent on the parameter in TypeScript is via overload declarations. Something like this should work:

static hashStr(str: string): string;
static hashStr(str: string, raw: false): string;
static hashStr(str: string, raw: true): Int32Array;
static hashStr(str: string, raw: boolean): Int32Array | string;
static hashStr(str: string, raw?: boolean): string | Int32Array {
    // implementation goes here...
}

I'd suggest posting an issue with ts-md5 about this.

Upvotes: 2

Fenton
Fenton

Reputation: 250902

You can use a type guard, or a type assertion.

type guard

let hash = Md5.hashStr(str);
if (typeof hash === 'string') {
    hash = hash.toUpperCase();
}

type assertion

let hash = (<string>Md5.hashStr(str)).toUpperCase();

The benefit of the type guard is that it technically safer - because if you ever did get something that wasn't a string at runtime, it would still work. The type assertion is simply you overriding the compiler, so it isn't technically as safe, but it is entirely erased and therefore results in the same runtime code you have at the point you have the error.

Upvotes: 2

Related Questions