GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Improved union/intersection type inference by ahejlsberg · Pull Request #5738 · microsoft/TypeScript

Conversation

@ahejlsberg

@ahejlsberg Anders Hejlsberg (ahejlsberg) commented Nov 20, 2015

Copy link
Copy Markdown
Member

This PR improves type inference involving source and target sides that are both union or intersection types. When inferring from a type S to a type T, if S and T are both union types or both intersection types, we first reduce S and T by removing constituents that are matched by a constituent in the other type. For example, when inferring from string | string[] to string | T, we reduce the types to string[] and T, thus inferring string[] for T.

An example:

type Maybe<T> = T | void;

function isDefined<T>(x: Maybe<T>): x is T {
    return x !== undefined && x !== null;
}

function isUndefined<T>(x: Maybe<T>): x is void {
    return x === undefined || x === null;
}

function getOrElse<T>(x: Maybe<T>, defaultValue: T): T {
    return isDefined(x) ? x : defaultValue;
}

function test1(x: Maybe<string>) {
    let x1 = getOrElse(x, "Undefined");         // string
    let x2 = isDefined(x) ? x : "Undefined";    // string
    let x3 = isUndefined(x) ? "Undefined" : x;  // string
}

function test2(x: Maybe<number>) {
    let x1 = getOrElse(x, -1);         // number
    let x2 = isDefined(x) ? x : -1;    // number
    let x3 = isUndefined(x) ? -1 : x;  // number
}

Fixes #2264.
Fixes #4212.
Fixes #5417.
Fixes #5456.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Anders Hejlsberg (ahejlsberg) added 3 commits November 20, 2015 10:07
@ahejlsberg
Reduce union and intersection types before inference
dc629d5
@ahejlsberg
Adding tests
a0842aa
@ahejlsberg
Accepting new baselines
11f4e3c
@msftclas Microsoft Contribution License Agreements (msftclas) added the cla-not-required label Nov 20, 2015
sandersn
sandersn reviewed Nov 20, 2015
View reviewed changes
Comment thread src/compiler/checker.ts

@sandersn Nathan Shively-Sanders (sandersn) Nov 20, 2015

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about

return forEach(target.types, t => isTypeIdenticalTo(source, t) || undefined);

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@ahejlsberg Anders Hejlsberg (ahejlsberg) Nov 24, 2015

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely an option, but not quite as efficient. I will keep what's there.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@sandersn

Nathan Shively-Sanders (sandersn) commented Nov 20, 2015

Copy link
Copy Markdown
Member

👍

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ahejlsberg
Fix linting errors
add5146
DanielRosenwasser
DanielRosenwasser reviewed Nov 23, 2015
View reviewed changes
Comment thread src/compiler/checker.ts

@DanielRosenwasser Daniel Rosenwasser (DanielRosenwasser) Nov 23, 2015

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you break this into multiple lines?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@ffMathy Mathias Lykkegaard Lorenzen (ffMathy) Dec 7, 2015

Copy link
Copy Markdown

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use wordwrapping man.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Anders Hejlsberg (ahejlsberg) added a commit that referenced this pull request Nov 24, 2015
@ahejlsberg
Merge pull request #5738 from Microsoft/unionIntersectionTypeInference
ea0cc79
Improved union/intersection type inference
@ahejlsberg
Anders Hejlsberg (ahejlsberg) merged commit ea0cc79 into master Nov 24, 2015
This was referenced Nov 24, 2015
Inference fails for return-type of intersection between class and generic type #5456
Closed
Inference doesn't work with union types #2264
Closed
Type parameters in custom type guards don't seem to have the same meaning as in their predicates #4212
Closed
Type argument inference doesn't seem to work correctly with generic type aliases #5417
Closed
@RyanCavanaugh
Ryan Cavanaugh (RyanCavanaugh) deleted the unionIntersectionTypeInference branch November 24, 2015 22:23
@mariusschulz

Marius Schulz (mariusschulz) commented Nov 29, 2015

Copy link
Copy Markdown
Contributor

Anders Hejlsberg (@ahejlsberg) You've got a little typo in your code example: isUndefined<T> should use or rather than and, shouldn't it? Just trying to avoid confusion here.

function isUndefined<T>(x: Maybe<T>): x is void {
    return x === undefined || x === null;
}
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ahejlsberg

Anders Hejlsberg (ahejlsberg) commented Nov 29, 2015

Copy link
Copy Markdown
Member Author

Marius Schulz (@mariusschulz) Yes indeed, thanks for catching that.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vladima Vladimir Matveev (vladima) mentioned this pull request Dec 1, 2015
Massive slowdown in compiling complicated union types #5849
Closed
@ahejlsberg Anders Hejlsberg (ahejlsberg) mentioned this pull request Dec 2, 2015
Fix union type parameter inference #5895
Merged
@david-driscoll David Driscoll (david-driscoll) mentioned this pull request Dec 3, 2015
Update typings for combineLatest ReactiveX/rxjs#871
Closed
@vladima Vladimir Matveev (vladima) mentioned this pull request Dec 3, 2015
Port union reduction to 1.7 #5919
Merged
This was referenced Dec 5, 2015
Fix union/union or intersection/intersection type inference #5942
Merged
TypeScript compiler hangs case #4604
Closed
@ENikS

Eugene Sadovoi (ENikS) commented Dec 7, 2015

Copy link
Copy Markdown

Will this address issue mentioned in #3215 ?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ahejlsberg

Anders Hejlsberg (ahejlsberg) commented Dec 8, 2015

Copy link
Copy Markdown
Member Author

Eugene Sadovoi (@ENikS) No, the two are unrelated.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@HerringtonDarkholme Herrington Darkholme (HerringtonDarkholme) mentioned this pull request Dec 11, 2015
Unions Types and User Defined Type Guard basarat/typescript-book#46
Open
@masaeedu

Asad Saeeduddin (masaeedu) commented Feb 9, 2016

Copy link
Copy Markdown
Contributor

Anders Hejlsberg (@ahejlsberg) Would inferring T more accurately in the following scenario be worthwhile:

interface A { a: any; }

function test<T>(arg: A & T): T { ... }

let result = test({a: "", b: 10});

The type of result is inferred as {}, although I would expect it to be inferred as {b: number}. Admittedly I don't have a very clear use case for this at the moment.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ahejlsberg

Anders Hejlsberg (ahejlsberg) commented Feb 9, 2016

Copy link
Copy Markdown
Member Author

Asad Saeeduddin (@masaeedu) We could potentially explore that, but it could get complex and would require type inference to manufacture new types, neither of which I'm crazy about. Specifically, in your example, we'd have to manufacture a new type { b: number } and infer that for T. I think it is desirable to have the property that type inference never infers types that don't already occur in your code.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@microsoft Microsoft (microsoft) locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

8 participants

@ahejlsberg @sandersn @mariusschulz @ENikS @masaeedu @DanielRosenwasser @ffMathy @msftclas
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.