microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.82k stars 12.46k forks source link

Cannot find namespace `module.SomeClass` when used as type even though module exports it with `export default { SomeClass }` #60342

Open elisee opened 3 hours ago

elisee commented 3 hours ago

πŸ”Ž Search Terms

using type of class in default export using types of a module with a default export containing with a class cannot find namespace

πŸ•— Version & Regression Information

This is the behavior in every version I tried, and I reviewed the FAQ for entries about default imports and exports

⏯ Playground Link

https://www.typescriptlang.org/dev/bug-workbench/?ts=5.7.0-dev.20241025#code/PTAEAEDMEsBsFMB2BDAtvAXKAzvAxgPaIAmyATgJ4B0ALtgFB6zLbagDKB6Aws66AG8AvvXgAPAA4EyNUMXiRkAV1iyBHLvF4s2I+iAgwEKdFglloqctTr1LUmTnxFSlUJDJdQAIirBchCTW3gDc9AiyAPrIWAEu1lScPHzYYUA

πŸ’» Code

// @filename: secondary.ts
class SomeClass {}
export default { SomeClass }

// @filename: primary.ts
import secondary from "./secondary";
let _a: secondary.SomeClass; // Error 2503: Cannot find namespace 'secondary'.

πŸ™ Actual behavior

TypeScript reports "Cannot find namespace 'secondary'."

πŸ™‚ Expected behavior

TypeScript resolves secondary.SomeClass and lets me use it as the type of a variable

Additional information about the issue

This is a minimal repro of an issue I encounter when default exporting a bunch of classes each in their own file and then re-exporting them from a common module with export default { ClassA, ClassB, ClassC }.

Using the class as a constructor as in let _a = new secondary.SomeClass(); does work, just not as a type.

Screenshot of the error in VSCode:

Image

Andarist commented 3 hours ago

To access this type you need to use typeof secondary.SomeClass

elisee commented 2 hours ago

To access this type you need to use typeof secondary.SomeClass

This does not yield the desired result, as can be seen here:

// @filename: secondary.ts
class SomeClass {}
export default { SomeClass }

// @filename: primary.ts
import secondary from "./secondary";
let a: typeof secondary.SomeClass;
a = new secondary.SomeClass(); // Error 2741: Property 'prototype' is missing in type 'SomeClass' but required in type 'typeof SomeClass'.

Workbench Repro

elisee commented 2 hours ago

Somehow it seems that let a: typeof secondary.SomeClass.prototype; does the trick. But that seems like a strange way to express that type. Am I misunderstanding something, is there really something inherent about default exports that prevents TypeScript from exposing the class type directly, or is it a bug?