Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Applying a known operator to a union type should be inferred as the corresponding union type #40608

Closed
5 tasks done
sharshuv-quotient opened this issue Sep 17, 2020 · 2 comments
Labels
Duplicate An existing issue was already created

Comments

@sharshuv-quotient
Copy link

Search Terms

union type, operators, inference, numbers, math, calculation, addition, multiplication

Suggestion

Given a union type of numbers, or strings (for example -1 | 1), when we apply a known operator on it (for example 2 * x) it currently result in type number. Though it is possible to make this type stronger by inferring the type -2 | 2 from it.

Examples

const x: -1 | 1 = 1;
const y: -1 | 1 = -x; // currently error though true
const x: 1 | 2;
const y: 3 | 4;
const z: 3 | 4 | 6 | 8 = x * y; // currently error though true

We can do this with strings too:

const x: 'A' | 'D'
const y: 'C' | 'D'
const z: 'AC' | 'DC' | 'AD' | 'DD' = x + y;

Use Cases

For example writing a comparator function:

myComparator(item1, item2): -1 | 0 | 1 {
  if (direction === 'desc') {
    return -myComparator(item1, item2); // this will currently result in an error, though it's obviously true
  }
...
}

Another example,
Let's say I'm using a string to code some sort of information.

declare const verticalDirection: 'TOP' | 'BOTTOM';
declare const horizontalDirection: 'LEFT' | 'RIGHT';
const direction: 'TOP_LEFT' | 'TOP_RIGHT' | 'BOTTOM_LEFT' | 'BOTTOM_RIGHT' = 

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
    Anything that was considered number before, will be considered a more specific case of number, thus still assignable to number.
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.
@andrewbranch
Copy link
Member

To be clear, your suggestion has nothing to do with union types. Operations on unions either are distributive, or can be made distributive with a conditional type:

type T1 = `${'TOP' | 'BOTTOM'}_${'LEFT' | 'RIGHT'}`; // 'TOP_LEFT' | 'TOP_RIGHT' | 'BOTTOM_LEFT' | 'BOTTOM_RIGHT'
type T2 = { x: number, y: string }['x' | 'y']; // number | string
type T3 = Partial<string | number | undefined | { x: number }>; // string | number | undefined | { x?: number }

What doesn’t exist that you’re suggesting is type-level arithmetic (and string concatenation), with or without unions:

declare const x: 1;
const y = -x; // number

declare const s1: 'top';
const s2 = s1 + '-left'; // string

Here’s another:

declare const b1: true;
const b2 = !b1; // boolean

Which makes this a duplicate of #15645/#26382. (Even though your suggestion isn’t specifically limited to numerical arithmetic, I think the design considerations are about the same.)

@andrewbranch andrewbranch added the Duplicate An existing issue was already created label Sep 17, 2020
@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

3 participants