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 — Infer from generic function return types by ahejlsberg · Pull Request #16072 · microsoft/TypeScript

Conversation

@ahejlsberg

@ahejlsberg Anders Hejlsberg (ahejlsberg) commented May 25, 2017 •
edited
Loading

Uh oh!

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

Copy link
Copy Markdown
Member

With this PR we improve type argument inference by inferring from the contextual type of a generic function call to the return type of the generic function. For example:

function emptyArray<T>(): T[] {
    return [];
}

let a1: string[] = emptyArray();  // string inferred for T
let a2: number[] = emptyArray();  // number inferred for T

Previously the two assignments above would error because {} was inferred for T. We now infer from the contextual type (i.e. the type of the variable to which the function result is assigned).

A more elaborate example:

function arrayFilter<T>(f: (x: T) => boolean): (a: T[]) => T[] {
    return a => a.filter(f);
}

function arrayMap<T, U>(f: (x: T) => U): (a: T[]) => U[] {
    return a => a.map(f);
}

function compose<A, B, C>(f: (x: A) => B, g: (x: B) => C): (x: A) => C {
    return x => g(f(x));
}

const positives: (a: number[]) => number[] = arrayFilter(x => x >= 0);
const lengths: (a: string[]) => number[] = arrayMap(s => s.length);
const evenLengths: (a: string[]) => number[] =
    compose(arrayMap(s => s.length), arrayFilter(x => x % 2 === 0));

let a1 = positives([1, 2, -3, 4, -5]);            // [1, 2, 4]
let a2 = lengths(['a', 'bb', 'ccc', 'dddd']);     // [1, 2, 3]
let a3 = evenLengths(['a', 'bb', 'ccc', 'dddd']); // [2, 4]

Inferences made from generic function return types have lower priority than inferences made from arguments to the generic function. For example, the type of s is inferred as string (not Object) in the following:

function filter<T>(a: T[], f: (x: T) => boolean): T[] {
    return a.filter(f);
}

let a: Object[] = filter(['a', 'bb', 'ccc', 'dddd'], s => s.length > 2);

This PR is a precursor for inferring higher order function types when no inferences can be made for one or more type parameters.

const wrapper = compose(x => [x], y => ({ p: y }));  // (x: {}) => { p: {}[] }

We currently infer (x: {}) => { p: {}[] }, but ideally we'd infer <A>(x: A) => { p: A[] }. That's next on the list.

Fixes #15680.

Sorry, something went wrong.

Uh oh!

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

abenhamdine, david-driscoll, stephenlaughton, KiaraGrouwstra, HerringtonDarkholme, alitaheri, Lenne231, dnavas77, arackaf, mohsen1, and 14 more reacted with thumbs up emoji benlesh, BANG88, wand3r, yortus, JoshuaKGoldberg, aluanhaddad, zpdDG4gta8XKpMCd, maxdavidson, jquintozamora, adammedford, and 22 more reacted with hooray emoji DanielRosenwasser, benlesh, trxcllnt, wand3r, alexrock, aluanhaddad, zpdDG4gta8XKpMCd, chasent, sean-vieira, david-driscoll, and 12 more reacted with heart emoji
All reactions
  • 👍 24 reactions
  • 🎉 32 reactions
  • ❤️ 22 reactions
Anders Hejlsberg (ahejlsberg) added 11 commits May 22, 2017 08:46
@ahejlsberg
Revise type inference data structures
24a25fd
@ahejlsberg
Initial implementation of return type inference
e19d934
@ahejlsberg
Clean up implementation
68056d5
@ahejlsberg
Accept new baselines
7dd9e21
@ahejlsberg
Merge branch 'master' into improveTypeArgumentInference
56ba186
@ahejlsberg
Fix fourslash test
0b37adc
@ahejlsberg
Fix linting errors
501d92a
@ahejlsberg
InferenceContext is-a TypeMapper instead of has-a TypeMapper
77e2f09
@ahejlsberg
Move return type inference to inferTypeArguments function
b8d5eff
@ahejlsberg
Add tests
f29d7df
@ahejlsberg
Accept new baselines
5fa0fb4
@msftclas Microsoft Contribution License Agreements (msftclas) added the cla-not-required label May 25, 2017
@ahejlsberg
Anders Hejlsberg (ahejlsberg) requested a review from Mohamed Hegazy (mhegazy) May 25, 2017 00:14
@benlesh

Ben Lesh (benlesh) commented May 25, 2017

Copy link
Copy Markdown

I was told "if you get Anders interested in your typings issue, it'll be implemented in a few hours"

Apparently the legend is real.

DanielRosenwasser, BANG88, tinganho, wand3r, saschanaz, billba, JoshuaKGoldberg, aluanhaddad, danielyogel, sean-vieira, and 36 more reacted with laugh emoji jwbay, s-panferov, otodockal, sean-vieira, KiaraGrouwstra, Igorbek, niieani, alitaheri, BrianMikinski, ErikCupal, and 4 more reacted with hooray emoji
All reactions
  • 😄 46 reactions
  • 🎉 14 reactions

Sorry, something went wrong.

Uh oh!

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

mhegazy
Mohamed Hegazy (mhegazy) reviewed May 25, 2017
View reviewed changes
Comment thread src/compiler/checker.ts
// not contain anyFunctionType when we come back to this argument for its second round
// of inference.
if (source.flags & TypeFlags.ContainsAnyFunctionType) {
if (source.flags & TypeFlags.ContainsAnyFunctionType || source === silentNeverType) {

@mhegazy Mohamed Hegazy (mhegazy) May 25, 2017

Copy link
Copy Markdown
Contributor

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.

worth adding a note on the use of silentNeverType as a marker here.

Sorry, something went wrong.

Uh oh!

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

All reactions
mhegazy
Mohamed Hegazy (mhegazy) reviewed May 25, 2017
View reviewed changes
Comment thread src/compiler/checker.ts Outdated
inferences.primary || (inferences.primary = []);
if (!contains(candidates, source)) {
candidates.push(source);
for (const inference of inferences) {

@mhegazy Mohamed Hegazy (mhegazy) May 25, 2017

Copy link
Copy Markdown
Contributor

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.

getInferenceInfoForType here as well?

Sorry, something went wrong.

Uh oh!

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

All reactions
mhegazy
Mohamed Hegazy (mhegazy) approved these changes May 25, 2017
View reviewed changes
@ahejlsberg Anders Hejlsberg (ahejlsberg) mentioned this pull request May 26, 2017
Bad type inference from return type #16099
Closed
@ahejlsberg
Address CR feedback
7ca91f8
@ahejlsberg
Anders Hejlsberg (ahejlsberg) merged commit bcf84f4 into master May 26, 2017
@DanielRosenwasser Daniel Rosenwasser (DanielRosenwasser) mentioned this pull request May 26, 2017
Design Meeting Notes, 5/26/2017 #16114
Closed
This was referenced May 27, 2017
Function composition challenge for type system #10247
Open
question: how can i create and return a generic function in TypeScript? #9949
Closed
@RyanCavanaugh

Ryan Cavanaugh (RyanCavanaugh) commented May 30, 2017

Copy link
Copy Markdown
Member

Why doesn't this fix #11152 ?

All reactions

Sorry, something went wrong.

Uh oh!

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

@mhegazy

Mohamed Hegazy (mhegazy) commented May 30, 2017

Copy link
Copy Markdown
Contributor

Why doesn't this fix #11152 ?

contextual type is not propagated/instantiated correctly yet.

All reactions

Sorry, something went wrong.

Uh oh!

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

@ahejlsberg Anders Hejlsberg (ahejlsberg) mentioned this pull request Jun 6, 2017
Contextual generic function types #16305
Merged
@masaeedu Asad Saeeduddin (masaeedu) mentioned this pull request Jun 9, 2017
Improve type inference for generic curried functions #15016
Closed
@DanielRosenwasser Daniel Rosenwasser (DanielRosenwasser) mentioned this pull request Jun 9, 2017
Design Meeting Notes, 6/9/2017 #16415
Closed
@masaeedu Asad Saeeduddin (masaeedu) mentioned this pull request Jun 12, 2017
Type inference defaults to '{}' in call sites. #5254
Closed
@ahejlsberg Anders Hejlsberg (ahejlsberg) mentioned this pull request Jun 14, 2017
Circular inference failure (regression) #16512
Closed
@SlurpTheo SlurpTheo mentioned this pull request Jun 15, 2017
'Discarding Parameters' plus 'Duck Typing' makes every parameter optional? #9352
Closed
@KiaraGrouwstra kiara (KiaraGrouwstra) mentioned this pull request Jun 15, 2017
Variants of R.map() and lost types typed-typings/npm-ramda#121
Open
@DylanRJohnston Dylan R. Johnston (DylanRJohnston) mentioned this pull request Jun 15, 2017
Left and Right don't unify gcanti/fp-ts#128
Closed
@KiaraGrouwstra

kiara (KiaraGrouwstra) commented Jun 26, 2017

Copy link
Copy Markdown
Contributor

Anders Hejlsberg (@ahejlsberg):

We currently infer (x: {}) => { p: {}[] }, but ideally we'd infer <A>(x: A) => { p: A[] }. That's next on the list.

If that's still outstanding, might there be any PR/branch we could follow on that?

All reactions

Sorry, something went wrong.

Uh oh!

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

This was referenced Jun 27, 2017
fleshing out type operators (discussion) #16392
Closed
TS/flow typings? sanctuary-js/sanctuary#254
Closed
@fangpenlin Fang-Pen Lin (fangpenlin) mentioned this pull request Jul 18, 2017
WebSocketSubjectConfig's resultSelector is excepting an not necessary generic type T ReactiveX/rxjs#2754
Closed
@KiaraGrouwstra kiara (KiaraGrouwstra) mentioned this pull request Jul 25, 2017
Optional Generic Type Inference #14400
Open
@johnnyreilly

John Reilly (johnnyreilly) commented Jul 26, 2017

Copy link
Copy Markdown

contextual type is not propagated/instantiated correctly yet.

Mohamed Hegazy (@mhegazy) - I'm liking the use of the word "yet" above 👍 😄

jcjolley, mtpultz, and nateabele reacted with thumbs up emoji
All reactions
  • 👍 3 reactions

Sorry, something went wrong.

Uh oh!

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

@simonbuchan Simon Buchan (simonbuchan) mentioned this pull request Jul 31, 2017
Typescript does not implicitly infers types when providing function as arguments? #17520
Closed
This was referenced Aug 15, 2017
Composition and generics typed-typings/npm-ramda#86
Open
Support TypeScript/Flow type annotations sweet-js/sweet-core#482
Open
@RyanCavanaugh Ryan Cavanaugh (RyanCavanaugh) mentioned this pull request Sep 11, 2017
Contextual typing does not flow backward through function return types to the function arguments #5256
Closed
@KiaraGrouwstra kiara (KiaraGrouwstra) mentioned this pull request Oct 7, 2017
Type errors for Ramda cookbook methods mapKeys and renameBy typed-typings/npm-ramda#273
Closed
@AlexGalays

Alexandre Galays (AlexGalays) commented Nov 2, 2017

Copy link
Copy Markdown

Where can we track progress against the following bug?

type Function1<T1, R> = (t1: T1) => R


function pipe<T1, R>(fn: Function1<T1, R>): Function1<T1, R> {
    return fn
}


/// test

function identity<A>(a: A): A { return a }


const pipedIdentity = pipe(identity)

// x is a {}, not a number
const x = pipedIdentity(33)
KiaraGrouwstra and nateabele reacted with thumbs up emoji
All reactions
  • 👍 2 reactions

Sorry, something went wrong.

Uh oh!

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

@gcnew

Marin Marinov (gcnew) commented Nov 2, 2017

Copy link
Copy Markdown
Contributor

Alexandre Galays (@AlexGalays) see #9366 and the linked issues.

KiaraGrouwstra and AlexGalays reacted with thumbs up emoji
All reactions
  • 👍 2 reactions

Sorry, something went wrong.

Uh oh!

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

@mhegazy
Mohamed Hegazy (mhegazy) deleted the improveTypeArgumentInference branch November 2, 2017 19:09
@microsoft Microsoft (microsoft) locked and limited conversation to collaborators Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Reviewers

1 more reviewer
@mhegazy Mohamed Hegazy (mhegazy) mhegazy approved these changes
Reviewers whose approvals may not affect merge requirements

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.

9 participants

@ahejlsberg @benlesh @RyanCavanaugh @mhegazy @KiaraGrouwstra @johnnyreilly @AlexGalays @gcnew @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.