You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
declarevarv: Record<string,string>;letv2={...v};// worksletv3={a: '', ...v};// index signature lostletv4={...v,a: ''};// same as aboveletv5={a: 1, ...v};// index signature lost, should be '{a: number, [x: string]: number | string}'letv6={[Number()]: 1, ...v};// empty object type ò,Ó, should be '{[x: string]: number | string}'
When you spread something with an index signature, should the resulting object have an index signature, or not?
Today, the answer is "no", but...it should probably be yes?
What do you do with properties in the object type that don't satisfy the index signature?
Intersections?
Unions just because the general assumption of covariance.
Paraphrased: "If you have something with an index signature, you know that all properties in the object must adhere to the index signature."
How close to a perfect identity should spreading something be?
Seems bizarre to discard it.
Maybe it's okay to discard the index signature, but not to discard the type of the index signature.
What does that mean?
Subsequent spread-in values with index signatures could possibly override a property with a different type later on.
So should we take a breaking change on v5 from the example?
Sounds like no?
Let's go case-by-case.
v2 has "good" behavior.
v3 you can make the argument that the object should keep the index signature as well.
v4 is a case where you can invalidate the index signature.
v5 is "easily debatable"
v6 this is "interesting" because it has an "inferred" index signature from the computed property that that doesn't have a literal value.
Well...it sounds like v2 and v3 are also "easily debatable".
letwat1: Record<string,number>={...v,a: 4};// worksletwat2: Record<string,number>={...v};// doesn't work
Seems like wat1 shouldn't work, but that would be a breaking change.
Index signatures should probably never make concrete properties go away.
How do optional properties work?
Those should never survive.
What are the principles?
Want to be conservative regarding spreads of things with index signatures.
Compute the worst-case resulting type of the index signature.
That would be a union of all spread-in index signatures unioned with any property types.
That might introduce undefineds for optional properties.
But it'll potentially override the underlying type.
But that's okay.
The resulting type of earlier properties should be "poisoned" by the types of subsequent spreads.
Effectively { a: 10, ...somethingWithAnIndex } should have a property of type a whose type is number | (typeof somethingWithAnIndex)[PropertyKey].
What do you think we should do with intersections of 10**33 members?
"It's a React component, so it's doing a little bit of composition or something."
The code gets every key of React.ReactHTML, and there's a LOT of properties on there!
Comp itself is effectively a union of every HTML element constructor.
When performing overload resolution, we try to create the intersection of all options bags that are expected.
When you try to get the type of ref on that intersection to see if yourref is compatible, then you create a REALLY big intersection since ref is a union of different types where each member gets intersected with the ref of every other object type.
Part of the issue is that the types are partially unsatisfiable - ref is expected to be a ref object, or a function, or a string, or null, or undefined.
Function types that are never expected to have properties should be thrown out.
Intersections of primitives and objects should be thrown out.
Unfortunately we don't.
Would be helpful if you could say "non-callable objects"
This could be done with the negated types branch.
Could also have unfulfillable signatures?
(...args: unknown[]) => never is effectively the bottom type for functions.
It's only properties that these things have in common that could ensue in an empty domain.
But you do have to construct the set of properties - thought that's not that expensive.
And you only have to do that for symbols that exist in both, don't need to resolve them.
Might be worth pursuing.
The text was updated successfully, but these errors were encountered:
The resulting type of earlier properties should be "poisoned" by the types of subsequent spreads.
Effectively { a: 10, ...somethingWithAnIndex } should have a property of type a whose type is number | (typeof somethingWithAnIndex)[PropertyKey].
Why is this different for object literals with inferred index signatures from computed properties?
letobj={a: 10,[String()]: 'foo'};
In this example { [x: string]: string | number; a: number; } is inferred. With your reasoning regarding index signatures in spread you would also need to change the inferred type of this object literal to { [x: string]: string | number; a: number | string; }
Rest enumeration fixes
Timebox: 10 minutes
#29616
#29676
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/propertyIsEnumerable
Symbol
polyfillSymbol
polyfill must be astring
anyway, so that branch of code would never run.master
is frozen for 2 weeks.globalThis
implicit any errorsTimebox: 15 minutes
#30139
this
in the global scope now has the typetypeof globalThis
.this
may now be an error.noImplicitAny
vsnoImplicitThis
noImplicitThis
errors tonoImplicitAny
.this
at the top level?this
at the top level have different behavior in JS strict mode? And in modules?--globalThis
needs to change its behavior under"use strict"
to includeundefined
in the type?any
types arising from element accesses to property accesses.noImplicitThis
useful now then?this
shadowing in functions.noImplicitAny
."use strict"
behavior.Dropped Index Signature for Spreads
Timebox: 15 minutes
#27273
ajafff@a626e4e
v5
from the example?v2
has "good" behavior.v3
you can make the argument that the object should keep the index signature as well.v4
is a case where you can invalidate the index signature.v5
is "easily debatable"v6
this is "interesting" because it has an "inferred" index signature from the computed property that that doesn't have a literal value.v2
andv3
are also "easily debatable".wat1
shouldn't work, but that would be a breaking change.undefined
s for optional properties.{ a: 10, ...somethingWithAnIndex }
should have a property of typea
whose type isnumber | (typeof somethingWithAnIndex)[PropertyKey]
.What do you think we should do with intersections of 10**33 members?
Timebox: 20 minutes
#30068
#29949
React.ReactHTML
, and there's a LOT of properties on there!Comp
itself is effectively a union of every HTML element constructor.ref
on that intersection to see if yourref
is compatible, then you create a REALLY big intersection since ref is a union of different types where each member gets intersected with theref
of every other object type.2**111
types created (~10**33
)ref
is expected to be a ref object, or a function, or a string, ornull
, orundefined
.(...args: unknown[]) => never
is effectively the bottom type for functions.The text was updated successfully, but these errors were encountered: