microsoft / microsoft/TypeScript

instanceof AbstractClass.constructor should narrow to typeof AbstracClass

Open
#28,936 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

In Discussion Suggestion
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
2d 4h
Merged PRs (30d)
132

Description

Please try to reproduce the issue with typescript@next. It may have already been fixed.

TypeScript Version: 3.3.0-dev.20181208

Search Terms: static instanceof constructor

Code

type Meta = {foo: string};
abstract class Abstract {
  static meta: Meta;
  public abstract toString(): string;
}

const getMeta = (fromModule: any): Meta | undefined => {
  return fromModule instanceof Abstract.constructor
    ? fromModule.meta : undefined;
};

Expected behavior:
Narrow the type of fromModule to typeof Abstract, so that static fields can be accessed.
(In Typescript versions <= 3.1.6 the above code didn't raise an error, my guess is that the type was not narrowed at all)

Actual behavior:
The narrowed type of fromModule is {}:

Error:(10, 18) TS2339: Property 'meta' does not exist on type '{}'.

Playground Link:
https://www.typescriptlang.org/play/index.html#src=%0D%0Atype%20Meta%20%3D%20%7Bfoo%3A%20string%7D%3B%0D%0Aabstract%20class%20Abstract%20%7B%0D%0A%20%20static%20meta%3A%20Meta%3B%0D%0A%20%20public%20abstract%20toString()%3A%20string%3B%0D%0A%7D%0D%0A%0D%0Aconst%20getMeta%20%3D%20(fromModule%3A%20any)%3A%20Meta%20%7C%20undefined%20%3D%3E%20%7B%0D%0A%20%20return%20fromModule%20instanceof%20Abstract.constructor%0D%0A%20%20%20%20%3F%20fromModule.meta%20%3A%20undefined%3B%0D%0A%7D%3B%0D%0A

Related Issues:
I found the following potentially related issues but they didn't seem to be an exact match or to old (because this problem only exists since 3.2.1):
- #27276
- #23274
- #16035

Workaround
Creating a type guard is of course doable for a single abstract class.

const extendsAbstract = (FromModule: unknown): FromModule is typeof Abstract =>
  FromModule && FromModule instanceof Abstract.constructor;

(Or maybe it could even be written in a generic way?)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the example in the linked TypeScript Playground with typescript@next, then compare the behavior with the reported 3.3.0-dev.20181208 version. Review related issues #27276, #23274, and #16035 before tracing the compiler's instanceof narrowing behavior. Done means the example narrows fromModule to typeof Abstract so the static meta field is accepted, with coverage for the regression.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.