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

Surprising behavior with typeof in signatures #22825

Closed
ajafff opened this issue Mar 23, 2018 · 6 comments
Closed

Surprising behavior with typeof in signatures #22825

ajafff opened this issue Mar 23, 2018 · 6 comments
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue Help Wanted You can do this

Comments

@ajafff
Copy link
Contributor

ajafff commented Mar 23, 2018

TypeScript Version: 2.9.0-dev.20180323

Search Terms:

Code

declare let foo: number;

// bar is of type string
// return type is string
declare function test(foo: string, bar: typeof foo): typeof foo;
// bar is of type string
// return type is number
declare function test({foo}: {foo: string}, bar: typeof foo): typeof foo;

Expected behavior:

typeof foo should reference the same declaration regardless of where it's used in the signature.

Actual behavior:

typeof foo in return type refers to the outer variable if foo comes from a destructured parameter. typeof foo inside the type annotation of another parameter refers to the parameter as expected.

This becomes even more visible if you remove the outer declare let foo: number; which will result in a compile error: Cannot find name 'foo'.

Playground Link: http://www.typescriptlang.org/play/#src=declare%20let%20foo%3A%20number%3B%0A%0Adeclare%20function%20test(foo%3A%20string%2C%20bar%3A%20typeof%20foo)%3A%20typeof%20foo%3B%0Adeclare%20function%20test(%7Bfoo%7D%3A%20%7Bfoo%3A%20string%7D%2C%20bar%3A%20typeof%20foo)%3A%20typeof%20foo%3B

Related Issues:
#22769 possibly related issue where the parameter initializer refers to the wrong variable.

@ajafff
Copy link
Contributor Author

ajafff commented Mar 23, 2018

It gets even weirder if you reference variables in the function body:

declare let foo: number;

// bar is of type string
// return type is number
function fn(bar: typeof foo): typeof foo {
    var foo = '';
    return bar; // compile error: string is not assignable to number
}

But if you change var to let it surprisingly works completely different:

declare let foo: number;

// bar is of type string
// return type is string
function fn(bar: typeof foo): typeof foo {
    let foo = '';
    return bar; // no compile error
}

@ghost
Copy link

ghost commented Mar 23, 2018

In declare function test({foo}: {foo: string}, bar: typeof foo): typeof foo;, there is an error at the second foo: src/a.ts(1,70): error TS2304: Cannot find name 'foo'.. You might have been confused because of #22790 ?

@ghost
Copy link

ghost commented Mar 23, 2018

I'll still mark this as a bug because I would expect the second example to have the same behavior regardless of whether you write var foo or let foo inside the function.

@ghost ghost added the Bug A bug in TypeScript label Mar 23, 2018
@ajafff
Copy link
Contributor Author

ajafff commented Mar 23, 2018

@andy-ms

there is an error at the second foo

If you copy and paste the whole snippet including the declare let foo: number; there will be no error.

Also that's what I meant with this note in the OP:

This becomes even more visible if you remove the outer declare let foo: number; which will result in a compile error: Cannot find name 'foo'.

@ghost
Copy link

ghost commented Mar 23, 2018

Ah, OK. So the problem is that we do name lookup differently in the return type vs in the parameter.

@ajafff
Copy link
Contributor Author

ajafff commented Mar 23, 2018

So the problem is that we do name lookup differently in the return type vs in the parameter.

Exactly. At least it should be consistent and not change if a parameter is destructured.

@mhegazy mhegazy added the Help Wanted You can do this label Mar 26, 2018
@mhegazy mhegazy added this to the Community milestone Mar 26, 2018
@mhegazy mhegazy added the Fixed A PR has been merged for this issue label Mar 28, 2018
@mhegazy mhegazy modified the milestones: Community, TypeScript 2.9 Mar 28, 2018
@microsoft microsoft locked and limited conversation to collaborators Jul 25, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue Help Wanted You can do this
Projects
None yet
Development

No branches or pull requests

2 participants