Reputation: 2394
I am using TypeScript and have a situation where a function returns a union of two types. It can either return a string or a model but I don't know how to get the type and perform an action based on what type was returned.
How would I do something like this? How are string and IMyModel being used as values in this example (as suggested by the error message)? The error seems confusing to me.
export interface IMyModel {
id: number;
name: string;
}
const myFunc = (value: boolean): string | IMyModel => {
if (value) return "a string";
return {
id: 12,
name: "model",
};
};
const a = myFunc(true);
if (a instanceof string) {
console.log("it is a string");
}
if (a instanceof IMyModel) {
console.log("it is a model");
}
I get the following static errors in visual studio code on the lines using instanceof
:
'string' only refers to a type, but is being used as a value here.ts(2693)
'IMyModel' only refers to a type, but is being used as a value here.ts(2693)
I also switched the interface to use "type" but that's the same.
Upvotes: 1
Views: 8063
Reputation: 1499
Typescript is a superset of javascript and ultimately compiles down to javascript. That being said it's important to think about what the code you are writing will look like as javascript. Here is what this will look like compiled:
const myFunc = value => {
if (value) return "a string";
return {
id: 12,
name: "model"
};
};
const a = myFunc(true);
if (a instanceof string) {
console.log("it is a string");
}
if (a instanceof IMyModel) {
console.log("it is a model");
}
You'll notice that the types you declared are compiled away. The error is starting to make a bit more sense now. We can't call instanceof
on a typescript type because they don't exist as far as the compiled javascript is concerned. You are probably looking for either:
if (typeof a === 'string') {
console.log("it is a string");
}
const isMyModel = (model: any): model is IMyModel => {
return typeof model === 'object' && Boolean(model.id && model.name)
}
if (isMyModel(a)) {
console.log("it is a model");
}
or both!
Upvotes: 1
Reputation: 37996
Right-hand parameter in object instanceof constructor
expression should be constructor/function.
The
instanceof
operator tests the presence ofconstructor.prototype
inobject
's prototype chain.
More info here
Back to your example. One of the possible solutions will be testing if typeof
a
is a 'string'
:
if (typeof a === 'string') {
a // a is of type string here
console.log("it is a string");
} else {
a // a is IModel
console.log("it is a model");
}
More on typeof type guards
Upvotes: 1
Reputation: 12491
To check if something is a string you would do it the same way as in JavaScript
if (typeof a === "string")
Interfaces are purely a TypeScript construct and to not exist in the transpiled JavaScript. Since it is a union you can make the assumption that if it is not a string it must be an IMyModel
.
Upvotes: 1