Short answer
(Almost) all type information are removed after compilation, and you can't use instanceof operator with an operand (T in your example) that does not exist at runtime.
Long answer
An identifier in TypeScript could belong to one or more of the following groups: type, value, namespace. What gets emitted as JavaScript is identifiers in the group of value.
Thus runtime operators only works with values. So if you want to do runtime type checking of the value of foo, you'll need to do the hard work yourself.
See the Declaration Merging section of the TypeScript Handbook for more information.
Answer from vilicvane on Stack OverflowShort answer
(Almost) all type information are removed after compilation, and you can't use instanceof operator with an operand (T in your example) that does not exist at runtime.
Long answer
An identifier in TypeScript could belong to one or more of the following groups: type, value, namespace. What gets emitted as JavaScript is identifiers in the group of value.
Thus runtime operators only works with values. So if you want to do runtime type checking of the value of foo, you'll need to do the hard work yourself.
See the Declaration Merging section of the TypeScript Handbook for more information.
To add to @vilcvane's answer: types and interfaces disappear during compilation, but some class information is still available. So, for example, this doesn't work:
interface MyInterface { }
var myVar: MyInterface = { };
// compiler error: Cannot find name 'MyInterface'
console.log(myVar instanceof MyInterface);
But this does:
class MyClass { }
var myVar: MyClass = new MyClass();
// this will log "true"
console.log(myVar instanceof MyClass);
However, it's important to note that this kind of test can be misleading, even when your code compiles with no errors:
class MyClass { }
var myVar: MyClass = { };
// no compiler errors, but this logs "false"
console.log(myVar instanceof MyClass);
This makes sense if you look at how TypeScript is generating the output JavaScript in each of these examples.
If typescript is duck-typed, how come when you use "instanceof", typescript accurately separate out the individual classes that implement the same interface? And how can we take advantage of this functionality in our typing?
Proposal: Type-side use of `instanceof` keyword as an instance-query to allow instanceof checking
Using instanceof in TypeScript to find return type of function results in "refers to a type, but is being used as a value here" - Stack Overflow
Can instanceOf operator be used to check if an object is an instance of a n interface, or type?
Videos
Edit: I know that instanceof checks at runtime, I'm very familiar with it and have been using it for many years. My question is specifically how the typing system works in typescript, how/why typescript is able to discern via type inference the difference between Error and PseudoError. And, given that it can, whether it is possible to leverage that kind of discernment to create a utility function that's based on this rather than based on shapes and interfaces.
In lib.es5.d.ts in typescript we have:
interface Error {
name: string;
message: string;
stack?: string;
}Now in my typescript file, if I create a new type, like this:
class PseudoError {
name = "hello"
message = "world"
stack? = "friends"
}And I do the following:
const test : PseudoError | Error = new PseudoError() type withoutError = Exclude<typeof test, Error> // <--- results to never, because of duck typing ?
The above is expected, because PseudoError and Error implement the same interface. So if I'm excluding Error, then I'm also excluding PseudoError by duck type standards.
But when I do this:
if (test instanceof Error) {
test // <--- hover over = Error
} else {
test // <--- hover over = PseudoError
}
It suggests that there is obviously some built-in functionality in typescript that doesn't work like in a duck-type-y way. This clearly aligns with the desired outcome in JS, but in my situation, I would like to have an Exclude<...> utility type that does the same thing as what typescript is doing behind the scenes with instanceof.
For example, where's this NotInstanceOf utility function?
const test : PseudoError | Error = new PseudoError() type withoutError = NotInstanceOf<typeof test, Error> // <--- results to PsuedoError
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:
typeof type guards
if (typeof a === 'string') {
console.log("it is a string");
}
User defined type guards:
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!
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.
I'm learning through [roadmap](https://roadmap.sh/typescript) and got stuck here (screenshot) where it says instanceOf can be used to check if an object is an instance of interface or type. I tried to do in code but it gives error.
The given code is invalid in TypeScript:
interface Person {
name: string;
age: number
}
const person = {
name: "Ken",
age: 25
}
if (person instanceof Person) // Error: 'Person' only refers to a type, but is being used as a value here.So am I using wrong? or that is a typo in that website? Any help would be highly appreciated. Thank!
Hello all,
Straight to the Point
I've recently started diving into TypeScript and at a high level I'm trying to achieve effective pattern matching. In short my question is: to achieve 'discriminated unions' (much like enums in Rust) should types with a kind property be used, or simply data classes that can be discriminated with instanceof.
.kind Property
I've encountered older docs that illustrate defining types with a kind property on which to discriminate.
type Shape = Square | Circle
type Square = {
kind: "square",
side: number
}
type Circle = {
kind: "circle",
radius: number
}
function printShapeProp(shape: Shape) {
if (shape.kind === 'square') {
console.log(shape.side)
} else if (shape.kind === 'circle') {
console.log(shape.radius)
}
}Class with instanceof
However newer docs don't seem to ever show discriminated unions, and it's starting to seem like the idiomatic way is to just define simple data classes and leverage the builtin instanceof operator.
class Shape {}
class Square extends Shape {
side: number
constructor (side: number) {
super()
this.side = side
}
}
class Circle extends Shape {
radius: number
constructor (radius: number) {
super()
this.radius = radius
}
}
function printShapeProp(shape: Shape) {
if (shape instanceof Circle) {
console.log(shape.radius)
} else if (shape instanceof Square) {
console.log(shape.side)
}
}Observations
One thing I noticed was the VSCode was much better at providing completion for shape.kind === '<choices>' than shape instanceof <choices>, where the former just showed me the possible values of circle and square, and the latter showed me a whole bunch of extraneous options.
Further I understand instanceof comes with many pitfalls, but I'm not sure they are relevant given your types are constrained to classes. From here I can only imagine the difference is in how flexible structural typing (type aliases) is compared to nominal typing (class names).