-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Closed
Labels
Design NotesNotes from our design meetingsNotes from our design meetings
Description
Rest enumeration fixes
Timebox: 10 minutes
#29616
#29676
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/propertyIsEnumerable
- This should only be an issue in ES3 if you're using a
Symbolpolyfill- Which means that your
Symbolpolyfill must be astringanyway, so that branch of code would never run.
- Which means that your
- Does it mean that you run into this when you're targeting ES5 but running in an ES2015 environment?
- Actually, object rest is an ES2017 feature, so downleveling is definitely legit.
- Action items: merge the PR and update tslib.
- TypeScript 3.5, since
masteris frozen for 2 weeks.
- TypeScript 3.5, since
globalThis implicit any errors
Timebox: 15 minutes
thisin the global scope now has the typetypeof globalThis.- That means that grabbing properties off of
thismay now be an error. - But it's unclear if the error should be under
noImplicitAnyvsnoImplicitThis - The change in 3.4 punts a bunch of
noImplicitThiserrors tonoImplicitAny.
- That means that grabbing properties off of
- What about people who want to avoid
thisat the top level?- That seems more like a lint rule.
- But doesn't
thisat the top level have different behavior in JS strict mode? And in modules?
- Maybe
--globalThisneeds to change its behavior under"use strict"to includeundefinedin the type? - One other thing to note is that when we know about a type, we'll give the specific type, but if a property doesn't exist, we pretend that it's okay.
- It basically extends implicit
anytypes arising from element accesses to property accesses.
- It basically extends implicit
- Why is
noImplicitThisuseful now then?- Catching untyped
thisshadowing in functions.
- Catching untyped
- Conclusion:
- Sounds like it's okay to move these into
noImplicitAny. - Account for
"use strict"behavior.
- Sounds like it's okay to move these into
Dropped Index Signature for Spreads
Timebox: 15 minutes
declare var v: Record<string, string>;
let v2 = {...v}; // works
let v3 = {a: '', ...v}; // index signature lost
let v4 = {...v, a: ''}; // same as above
let v5 = {a: 1, ...v}; // index signature lost, should be '{a: number, [x: string]: number | string}'
let v6 = {[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
v5from the example?- Sounds like no?
- Let's go case-by-case.
v2has "good" behavior.v3you can make the argument that the object should keep the index signature as well.v4is a case where you can invalidate the index signature.v5is "easily debatable"v6this 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
v2andv3are also "easily debatable".
let wat1: Record<string, number> = {...v, a: 4}; // works
let wat2: Record<string, number> = {...v}; // doesn't work- Seems like
wat1shouldn'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 typeawhose type isnumber | (typeof somethingWithAnIndex)[PropertyKey].
- Effectively
- Compute the worst-case resulting type of the index signature.
- Want to be conservative regarding spreads of things with index signatures.
What do you think we should do with intersections of 10**33 members?
Timebox: 20 minutes
- "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! Compitself 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
refon that intersection to see if yourrefis compatible, then you create a REALLY big intersection since ref is a union of different types where each member gets intersected with therefof every other object type.- [[Check this @weswigham]]
- And then you get
2**111types created (~10**33)
- The code gets every key of
- Sounds like it's heuristics time!
- ...or some sort of deferred operation time?
- well then it's just a land-mine down the road
- and it's already deferred anyway.
- ...or some sort of deferred operation time?
- Part of the issue is that the types are partially unsatisfiable -
refis expected to be a ref object, or a function, or a string, ornull, orundefined.- 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[]) => neveris 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.
Metadata
Metadata
Assignees
Labels
Design NotesNotes from our design meetingsNotes from our design meetings