microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.15k stars 12.38k forks source link

Confusing inferred names of anonymous classes #57626

Open Andarist opened 6 months ago

Andarist commented 6 months ago

πŸ”Ž Search Terms

inferred name anonymous class expando

πŸ•— Version & Regression Information

⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.5.0-dev.20240304#code/MYewdgzgLgBAhgJwQRhgXhgbQLoCheIqYAM26MwANnBBDAN4C++hyuA9OzAHoD8+uUJFhxyyYviHQYIAEYArcvVwx4ALgrVaDZs0HhpCAKYQArpVgY58gHRwOXVT35A

πŸ’» Code

const arr1 = []

arr1[0] = class {}

arr1
// ^? const arr1: (typeof 0)[]

const a = 10

const obj = {
  a: class {}
}

const result = obj.a
//    ^? const result: typeof a

πŸ™ Actual behavior

Symbols of anonymous classes are given inferred names based on the properties to which they are assigned to and that inferred name is used by typeof operator to refer to them

πŸ™‚ Expected behavior

I think that in both of those situations, the typeof inferredName display is somewhat confusing. However, the inferred name algorithm comes from JS spec so perhaps it's just "it is what it is" kind of situation.

This display doesn't convey any information about the scope that owns that name so the instinct is to look in the scope within which the declaration is. That name can exist there as a local binding and thus the information is a little bit confusing.

I get that this is... well, a convoluted situation :P I'm primarily reporting this because it's just something interesting that I've noticed here while investigating something entirely different. I don't necessarily care about the fix or this behavior - I'm just looking for some "working as intended"/"bug" confirmation here.

That said, I think that at the very least the inferred name should not come from an array index when dealing with auto-array types. Inferred names don't come from there in JS:

var arr1 = [class {}]
arr1[0].name // ''

var arr2 = []
arr2[0] = class {}
arr2[0].name // ''

Additional information about the issue

No response

fatcerberus commented 6 months ago

I'm going to go with "bug", because:

const arr1 = []

arr1.push(class {});

arr1
// ^? const arr1: (typeof (Anonymous class))[]

So TS does have the ability to display these as anonymous classes in type hints, but tries to be helpful and infer a name for the class, like JS would do. It's probably just an oversight that the name becomes nonsensical in the context of a typeof expression.

RyanCavanaugh commented 6 months ago

(typeof 0)[] does not make any sense

Andarist commented 6 months ago

Do u classify the other case (presented by obj) as working as intended?

RyanCavanaugh commented 6 months ago

Acknowledging that it's inconsistent, I think it'd be better to say (typeof obj)['a'], but at least typeof a is likely to be sensical in cases where a is a real identifier

fatcerberus commented 6 months ago

Sensical, but misleading. In the example given, typeof a at that position is number.