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

Inference of function pointer parameters for callback routines #16829

Closed
mqudsi opened this issue Jun 29, 2017 · 6 comments
Closed

Inference of function pointer parameters for callback routines #16829

mqudsi opened this issue Jun 29, 2017 · 6 comments

Comments

@mqudsi
Copy link

mqudsi commented Jun 29, 2017

I'm not sure if this is related to #15114, but I feel like it's a separate case.
Under Typescript 2.4.1, shouldn't type inference work here:

function map<T,R>(container: IterableIterator<T>, callback: (T) => R) : Array<R> {
    //omitted
}

function foo {
    map(new Map<number, number[]>.values(), v => v[0]);
}

The type for callback parameter v is never inferred. I have to explicitly declare it:

function foo {
    map(new Map<number, number>.values(), function (v: number[]) {
        return v[0];
    });
}

I don't see why the compiler can't figure this out from the typing of the map function?

@ghost
Copy link

ghost commented Jun 29, 2017

Your example contains a few typos. When they are fixed the example works.

function map<T,R>(container: IterableIterator<T>, callback: (t: T) => R) : Array<R> {
    return <any>null;
}

function foo() {
    map(new Map<number, number[]>().values(), v => v[0]);
}

@mqudsi
Copy link
Author

mqudsi commented Jun 29, 2017

Oh, that suddenly makes sense :)

As you can see, I'm new to typescript. Is there any way tsc can catch T => R as being a mistake?

@ghost
Copy link

ghost commented Jun 29, 2017

--noImplicitAny (or better, --strict, which includes it), because it was interpreting that as a parameter named T with no type.

@mqudsi
Copy link
Author

mqudsi commented Jun 29, 2017

I think I can't use that yet because I'm slowly migrating a JS project over, but I'll definitely turn that on when it becomes possible.

If I have a function declared like this:

function foo<T>((t: T) => R) {

Is there anything sane I could do with t? As in, is there a reason why I would include a name for a parameter that probably only exists for type deduction? I'm trying to understand why in a function declaration in a parameter to a function, the left-hand side of the call presumes a single T is an untyped parameter rather than a unnamed type. It had no problem deducing that R was an unnamed type rather than a reference to a (likely undeclared) variable named R.

@ghost
Copy link

ghost commented Jun 29, 2017

TypeScript always expects parameters to have names for the sake of documentation, even if those parameters appear as part of a type. So if you type:

function foo<T, R>(x: T, f: (t: T) => R): R { return f(x); }
foo(1, /*cursor*/

You'll get useful signature help.
There would be no good reason to include a name for R since that is usually covered by the name of the function itself. (This is why @returns documentation is usually redundant.)

@mqudsi
Copy link
Author

mqudsi commented Jun 29, 2017

Thanks.

@mqudsi mqudsi closed this as completed Jun 29, 2017
@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.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant