Conversation
🦋 Changeset detectedLatest commit: 31096c7 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@provide also support optional properties.@provide also support optional properties.
|
I think the reason I didn't make this change when I did the change for const fooContext = createContext<string>('foo');
class Parent extends LitElement {
@provide({context: fooContext})
foo?: Foo;
render() { return html`<x-child></x-child>`; }
}
class Child extends LitElement {
@consume({context: fooContext})
foo?: Foo;
}In this case because we have a context of a But that's difficult to differentiate from this case: const fooContext = createContext<string | undefined>('foo');
class Parent extends LitElement {
@provide({context: fooContext})
foo?: Foo;where it would be ok to provide a value of So I think that either:
|
|
I think we can use a type like this to distinguish between the case where the context allows undefined (in which case an optional field is fine) from the case where it isn't. type LooseRecord<K, V> =
V extends undefined ?
Partial<Record<K, V>> :
Record<K, V>;I'll try it out and add some tests |
Also add type checking tests
|
This ended up turning into a slightly bigger change, but I added support for providing and consuming optional properties (with correct type checking), and private/protected properties (with no type checking), and with no changes to the authoring experience. Also added type checking tests using |
@provide also support optional properties.@provide and @consume support optional and private properties.
|
Fixes #3883 |
|
@rictic Thanks for this! |
AndrewJakubowicz
left a comment
There was a problem hiding this comment.
Wow! There are some advanced types on display here.
TIL: about how to get around distributive conditional type behavior using square brackets!
Great use of type only tests which are necessary with such a complex change. The two types: FieldMustMatchProvidedType and FieldMustMatchContextType are very similar. Is it possible (or worthwhile) refactoring them into a single type?
.changeset/eighty-bananas-drive.md
Outdated
|
|
||
| Improve type checking of @provide and @consume. We now support optional properties, and public properties should be fully type checked. | ||
|
|
||
| This also adds support for using @provide and @consume with protected and private fields, but be aware that do to limitations in TypeScript's experimental decorators, the connection between the context and the property can not be type checked. We'll be able to fix this when standard decorators are released (current ETA TypeScript 5.2 in August 2023). |
There was a problem hiding this comment.
Nits:
- Code blocks around
@provideand@consume. - Typo: "but be aware that
dodue to limitations" - Is there an issue tracking fixing this when standard decorators are released?
This info should also be added to https://lit.dev/docs/data/context/#context-type-checking
There was a problem hiding this comment.
- Done
- Done
- Added!
And sent over as lit/lit.dev#1134
|
|
||
| Note that ContextRoot uses [WeakRefs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef) which are not supported in IE11. | ||
|
|
||
| ### Protected / Private Properties |
There was a problem hiding this comment.
Worth mentioning that standard private fields do not work (If I understand correctly)?
| assert.strictEqual(consumer.optionalValue, undefined); | ||
| assert.strictEqual(consumer.consumeOptionalWithDefault, undefined); | ||
| provider.optionalValue = 500; | ||
| await provider.updateComplete; |
There was a problem hiding this comment.
Can this be removed? - noting because in the test above only the consumer is awaited.
There was a problem hiding this comment.
Actually both awaits can be removed. Done
| } | ||
| } | ||
|
|
||
| suite('compilation tests', () => { |
There was a problem hiding this comment.
No action required - is it possible to add a failing compilation test with a standard private field? Maybe linked to a TODO with issue?
| // this code doesn't need to run, it's tested by tsc | ||
| if (true as boolean) { | ||
| return; | ||
| } |
There was a problem hiding this comment.
Clever way to skip everything.
| Obj, | ||
| Key extends PropertyKey, | ||
| ProvidedType, | ||
| ReturnValue |
There was a problem hiding this comment.
If ReturnValue is always void | any, is it something that can be hoisted out? E.g. type ReturnValue = void | any? Otherwise I expected it to possibly be parameterized.
| : // Next we check whether the object has the property as an optional field | ||
| Obj extends Partial<Record<Key, infer Providing>> | ||
| ? // Check assignability again. Note that we have to include undefined | ||
| // here on the consuming type because it's optional. |
There was a problem hiding this comment.
Nit: Should this comment reference the providing type?
| context: ContextType; | ||
| consuming: Providing | undefined; | ||
| } | ||
| : // Ok, the field isn't present, so either someone's using consume |
There was a problem hiding this comment.
Nit: "using consume provide"
Kept it as a local type alias so that there's a single place to put the comment about why we're using such a strange type.
Fixes #3732
As far as I can tell, the change just works. All tests still pass.