Repository: TypeScript
Issue: [Feature request] Union type operator that prefer narrow types over wide ones
Labels: Suggestion,Needs Proposal,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:
-->

narrow, types, type, wide. narrowing

## ✅ 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 -->

When `|` type operator is used to alternate types sometimes it is useful alternate its behaviour i.e. prefer more narrow type than more wide (to better understand look at example below). Something like `const` but not so strict. This type of behaviour will require to implement handilg for both sides of expression.

## 📃 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?
-->

This feature will help to better reflect dependency of one field on another (when both field are optional, but if one specified,  other should be too).

## 💻 Use Cases

<!--
  What do you want to use this for?
  What shortcomings exist with current approaches?
  What workarounds are you using in the meantime?
-->

Lets imagine (btw it is real world example) that we want autoconfigure navbar according to config of web app router. So when `navTitle` property is there and containg a string we are intrested in that element i.e. it will be placed on navbar with lable contained in `navTitle` property. And it shoud lead to somewhere, right? But to where? To figure it out we should know path. Thus `navTitile` property is dependent on `path` (which is optional by default in angular). OK! That is not a difficult issue:
```typescript
type Router = {path?: string, data?: any}

type RouterWithNavTitile = (RequiredProps<Router, "path"> & {navTitle: string})
type CustomRouterConfig = Router | RouterWithNavTitile
export type RequiredProps<T, P extends keyof T> = Omit<T, P> & Pick<Required<T>, P>

const test1: RouterWithNavTitile = {navTitle: "asd"} 

const test: CustomRouterConfig[] = [
  // all works as expected
  {path: "asd"},
  {navTitle:"asd", path:"asd"},
  // here is error. yeap. when navTitle present, path should be too but it is not here
  {navTitle:"asd"},
  {foo: "asd"}
]
```
Solution looks pretty good. Unless you are figurring out, that we should place all additional data into `data` property (this is angular way). Lets try:
```typescript
type RouteWithNavTitle = RequiredProps<Route, "path"> & {data: {navTitle: string}}
type RouteWithOptionalNavTitle = Route | RouteWithNavTitle

const test: RouteWithOptionalNavTitle[] = [
  // woops! No error! Path is required and not present! And no error
  {
    data: {
        navTitle: 'asd'
    }
  }
]
```
Why? That why! `Route | RouteWithNavTitle` will always resolve to `Route` since `RouteWithNavTitle` is narrowed `Route` (remeber `data` property? in route it is `any` but in `RouteWithNavTitle` it is narrowed to `{navTitile: string}`). Typescript will *always* prefer wider types for compatibility reasons. It is not always convinent as in considired example.

You may argue: "there is an `const` expressions". Yes. But they are too strict. 

To solve the preoblem i suggest `|&` operator which is more like regular `|` but will prefer narrow types when possible (when shape of object satisfy narrowed variant i.e. it can be assigned to more narrow variant).  It will require to implement handling of *both* sides of expression (in this example for `Route` and `RouteWithNavTitle`).

P.S. Thank you very much for reading this. Leave your comments for me to understand if i missed something or explained wrong.