Repository: TypeScript
Issue: Importing a type with the same name as a namespace import, ideally alongside it
Labels: Suggestion,Awaiting More Feedback

# Suggestion


## 🔍 Search Terms

<!--
  💡 Did you know? TypeScript has over 2,000 open suggestions!
  🔎 Please search thoroughly before logging new feature requests as most common ideas already have a proposal in progress.
  The "Common Feature Requests" section of the FAQ lists many popular requests: https://github.com/Microsoft/TypeScript/wiki/FAQ#common-feature-requests

  Replace the text below:
-->

import, type, module, namespace import,

## ✅ Viability Checklist

<!--
   Suggestions that don't meet all these criteria are very, very unlikely to be accepted.
   We always recommend reviewing the TypeScript design goals before investing time writing
   a proposal for ideas outside the scope of the project.
-->
My suggestion meets these guidelines:

* [x] This wouldn't be a breaking change in existing TypeScript/JavaScript code
* [x] This wouldn't change the runtime behavior of existing JavaScript code
* [x] This could be implemented without emitting different JS based on the types of the expressions
* [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
* [x] This feature would agree with the rest of [TypeScript's Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).


## ⭐ Suggestion

<!-- A summary of what you'd like to see added or changed -->

Being able to do write something like this:
```typescript
import * as Foo, type { Foo } from './Foo.js';
```

A more conservative request would be:
```typescript
import * as Foo from './Foo.js';
import type { Foo } from './Foo.js';
```

## 📃 Motivating Example

<!--
  If you were announcing this feature in a blog post, what's a short explanation that shows
  a developer why this feature improves the language?
-->

```typescript
import * as Foo, type { Foo } from './Foo.js';

// no need to write Foo.Foo    vvv
const someFunction = (someFoo: Foo) => ...
```

## 💻 Use Cases

<!--
  What do you want to use this for?
  What shortcomings exist with current approaches?
  What workarounds are you using in the meantime?
-->

It's a common pattern in functional programming to substitute classes with modules. this has several advantages (tree-shakability, no `this` binding, etc.).

These modules bundle functions which operate on some data and a type that identifies this data.
```typescript
export type Foo = [string, (a: any) => unknown];

export const unit = (): Foo => ['', (x: any) => x];

export const concat = (self: Foo, a: Foo) =>
    [self[0] + a[0], (x: any) => a[1](self[1](x))];
```
The problem is that when you need to mention the type of the data when it's imported as a namespace, you find yourself repeating the name twice:

```typescript
import * as Foo from './Foo.js';

const someFunction = (someFoo: Foo.Foo) => ...
```

On top of looking a little bit awkward, this is really not convenient when the name gets longer, but you don't want to import members directly because a function name like `concat` is likely to create collisions and aliasing it to `concatFoo` is a chore and can make the imports section of a file very noisy and unreadable.

I encountered this problem in my one code but also in libraries like [fp-ts](https://github.com/gcanti/fp-ts) and [Effect](https://github.com/Effect-TS/).

A module can also export types that it requires, like input types, so the more ambitious request would not only be useful for mentioning the "constructor" type, although this use case is less important.

A workaround is to export an alias (something like `Foo.Of` or `Foo.Self`):
```typescript
export { Foo as Self }
```
If we are talking about a library, this is something the maintainer needs to support and it's not *that* self-explanatory.

Another option is to create a type alias in the importing file
```
import * as Foo from './Foo.js';
type Foo = Foo.Foo;
```
If our type requires generics and type constraints, this becomes a real chore on top of requiring maintenance.

It would be consistent with the behaviour of the latter workaround to support the more conservative request. At current it yields the error `Duplicate identifier 'Foo'`, which is a little weird since values and types live in different worlds.