Repository: TypeScript
Issue: `extends` or `implements` clause on namespaces
Labels: Suggestion,Awaiting More Feedback

# Suggestion

<!--
  Please fill in each section completely. Thank you!
-->

## 🔍 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:
-->

List of keywords you searched for before creating this issue. Write them down here so that others can find this suggestion more easily and help provide feedback.

* *Namespace extends*
* *constrain namespaces*
* *type narrowing namespaces*

## ✅ 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 -->

Namespaces have been somewhat neglected in my opinion. I hardly use them, even though I try desperately to. I believe it is because they don't support mine and possible others' programming style. I like to be very explicit about my types, while keeping as much as possible inline. Therefore, I'm proposing an optional `extends` or `implements` (specifics to be decided) clause on a namespace specification. This would restrict the members that can be **exported** from the namespace, while leaving everything else defined inside it unaffected. This is useful as namespaces act like regular JS objects, so allowing the specification of an `extends` or `implements` clause would be like declaring and implementing an interface in one go. 

## 📃 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

export enum RequestType {
    launch,
    kill,
    authorise,
    share
}

export enum Signal {
    Ok,
    Error_Denied
    Error_Invalid
}

export namespace RequestHandlers extends Record<keyof typeof RequestType, () => Signal> {
    export function launch() {
        // ...
        return Signal.Ok
    }
    // ...
}

export default function handleRequest<Handler extends keyof typeof RequestHandlers>(request: Handler): ReturnType<RequestHandlers[Handler]> {
    if (request in RequestHandlers)
        return requestHandlers[request]();
}

```

## 💻 Use Cases

<!--
  What do you want to use this for?
  What shortcomings exist with current approaches?
  What workarounds are you using in the meantime?
-->

1. Interfaces allow us to define a type in the form of an object. If for instance the interface will only be used once in a map of types, then implementing it would be possible without the need to declare a separate binding. 
2. Typescript emits a function when declaring a namespace [see playground](https://www.typescriptlang.org/play?target=99#code/HYQwtgpgzgDiDGEAEUD2kAuALAlsA5qgE6rYRFIDeAUNUvUhAB4zEZLyrBTthIC8SAOQ8iefEIDctBoxZskGAJ4xkAIwFJgAVzBry0ug2asi7AGbbg8DDi5I1AGxBYAFAEoqMhgF9qPoA), it only seems fitting that the type be constrainable in some way or another, and this way seems really clean to me. 
3. It would help with code segregation, as the need to declare maps for easy reuse would require exporting a binding (depending on circumstances). Namespaces are better suited to this, as they provide a cleaner interface for doing this.