Repository: TypeScript
Issue: Manually widen a type for conditional/mapped type
Labels: Suggestion,Awaiting More Feedback

## Search Terms

`manual widen`

## Suggestion

I would like some keyword or other mechanism to refer to the widened version of a type, e.g. `widened 42` would be `number` and `widened 'foo'` would be `string`. Importantly, `widened 42 & { foo: 'bar' }` would be `number & { foo: 'bar' }`.

## Use Cases

Our project uses a ton of [branded primitives](https://github.com/Microsoft/TypeScript/wiki/FAQ#can-i-make-a-type-alias-nominal), which are accomplished by casting a number or string to `number & Branding` or `string & Branding`. We use this for all sorts of things: we have `number & Pixels` to indicate that a number is in pixels (and to force numbers passed to a function expecting pixels to use a number branded as pixels), we use `string & Url` to indicate a string is a URL, and so on.

We also have functions that operate on these types in a generic fashion, where we want to retain the branding. For example,

```ts
declare function plus<N extends number>(a: N, b: N): N;
```

This `plus` function is supposed to make sure we are adding pixels to pixels (or whatever unit), and retain the fact that their sum is also a number of pixels.

The problem comes in when we also have `const offset = 5 as 5 & Pixels;`. We define it as having that literal value for convenience (mostly, it shows up in Intellisense), and we have quite a few of these. More relevantly, the implementations of `times` and `dividedBy` (which I’m avoiding putting here as they are vastly more complex to cover canceling out units) can and should be able to take just plain numbers, but when I call `times(offset, 2)` it is inferred as `times<Pixels, 2>` and the return value retains the `2` even though obviously the runtime value is almost-certainly not going to be `2`.

I asked [for a solution to this on Stack Overflow](https://stackoverflow.com/q/56497519/778430), and was informed the only solution was to manually recreate the type by covering all of the potential brandings—which I basically have done, except that in the end there needs to be a generic overload, because we have a lot of situations where these functions are called by functions/classes that are also generic, and so only have `N extends number`, so the only overload available is the final one—which just retains whatever `N` was, even if `N` was a literal. I want to use `widen N` instead.

## Examples

```ts
const c = 5 as const;
const w: widened typeof c = 3;

function plus<N extends number>(a: N, b: N): widened N {
    return a + b;
}
class Pixels { private '__ in': 'pixel'; }
const offset = 5 as 5 & Pixels;
declare const width: Pixels;

const offsetWidth = plus(width, offset); // Pixels, not 5 & Pixels
```

## Checklist

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, etc.)
* [x] This feature would agree with the rest of [TypeScript's Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).