Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
404 views
in Technique[技术] by (71.8m points)

javascript - TypeScript instanceof not working

I'm having issues using the instanceof operator and it doesn't seem to work. Here is a part of my code:

        const results = _.map(items, function(item: Goal|Note|Task, index: number) { 
            let result = {};
            if (item instanceof Goal) {
                result = { id: index, title: item.name };
            } else if (item instanceof Note) {
                result = { id: index, title: item.content.text };
            } else if (item instanceof Task) {
                result = { id: index, title: item.name };
            }

            console.log(item);
            console.log(item instanceof Goal);
            console.log(item instanceof Note);
            console.log(item instanceof Task);

            return result; 
        });

All of my logs say false, here is what the console looks like:

No type matched

None of them match, despite being explicit that only the 3 types would be possible. You could also see the object itself with a typename of Goal, so I don't get why it doesn't match with instanceof Goal.

Any ideas?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

instanceof will return true only if it matches the function or class from which it was constructed. The item here is a plain Object.

const a = { a: 1 } // plain object
console.log(a);

// {a:1}                 <-- the constructor type is empty
//   a: 1
//   __proto__: Object   <-- inherited from

a instanceof A         // false because it is a plain object
a instanceof Object    // true because all object are inherited from Object

If it is constructed using a constructor function or a class, then instanceof will work as expected:

function A(a) {
    this.a = a;
}

const a = new A(1);    // create new "instance of" A
console.log(a);

// A {a:1}               <-- the constructor type is `A`

a instanceof A         // true because it is constructed from A
a instanceof Object    // true

If Goal is an Interface it will only check the structure of the object not its type. If Goal is a constructor then it should return true for instanceof checks.

Try something like:

// interface Goal {...}
class Goal {...}        // you will have to change the way it works.

items = [
   new Goal()
];

Update 2021:

Been playing with Typescript recently and came up with a better solution that works both in Typescript and JavaScript:

Try something like:

interface Goal {
    getCount(): number;
}

class Goal implements Goal {
    getCount() {
        return 3;
    }
}

function getItemCount(item: Goal | Note | Task) {
    return item instanceof Goal ? item.getCount() : 'not a goal';
}

console.log(getItemCount(new Goal()));  // 3
console.log(getItemCount('goal'));      // 'not a goal';

Here the interface and the class has the same name, so they can be used as both and type and an instance checker.

Changing the interface Goal signature or class Goal signature would throw something like:

TS2394: This overload signature is not compatible with its implementation signature.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...