S
SolidJS•2y ago
Braveheart

Typesafe <Show> only when store has data

the end result I want
return (
<Show when={mockDataStore}>
{mockDataStore.prop} // don't want this to be called giving runtime errors on render when mockDataStore has empty object
return (
<Show when={mockDataStore}>
{mockDataStore.prop} // don't want this to be called giving runtime errors on render when mockDataStore has empty object
I've tried various things like createStore<StoreType | {}>({}); -> results in ts errors X doesn't exist on {} re assigning store to previous declarations
const [mockDataStore2, setMockDataStore2] = createStore<StoreType | {}>({});

mockDataStore = mockDataStore2;
setMockDataStore = setMockDataStore2;
const [mockDataStore2, setMockDataStore2] = createStore<StoreType | {}>({});

mockDataStore = mockDataStore2;
setMockDataStore = setMockDataStore2;
the easy way around this is to create store type object of just empty values until the real values come, but that just seems lame :
const mockData: StoreType = {
companyName: 'Test Company',
date: new Date(),
selectType: 'Grocery',
address: {
addressLine1: '123 Test Street',
},
};
const [mockDataStore, setMockDataStore] = createStore<StoreType | {}>(mockData);
const mockData: StoreType = {
companyName: 'Test Company',
date: new Date(),
selectType: 'Grocery',
address: {
addressLine1: '123 Test Street',
},
};
const [mockDataStore, setMockDataStore] = createStore<StoreType | {}>(mockData);
28 Replies
foolswisdom
foolswisdom•2y ago
Try
<Show when={'date' in mockDataStore && mockDataStore}>
{mockDataStore => {
// rest of your code here
}}
</Show>
<Show when={'date' in mockDataStore && mockDataStore}>
{mockDataStore => {
// rest of your code here
}}
</Show>
(I used 'date', but any property should work)
Braveheart
BraveheartOP•2y ago
its never coming past <show now for me> I also tried this put it always passed <show
No description
Braveheart
BraveheartOP•2y ago
{mockDataStore => { just gives me syntax errors I also tried this signal but it always passed <Show when={dataLoaded()}> const [dataLoaded, setDataLoaded] = createSignal(false); and later setDataLoaded(true)
foolswisdom
foolswisdom•2y ago
I don't know what to tell you because this is syntactically valid 🤷
Braveheart
BraveheartOP•2y ago
i bit the bullet and did this
const [mockDataStore, setMockDataStore] = createStore<StoreType>({
companyName: 'Test Company 1',
date: new Date(),
selectType: 'Grocery',
address: {
addressLine1: '123 Test Street',
},
});
const [mockDataStore, setMockDataStore] = createStore<StoreType>({
companyName: 'Test Company 1',
date: new Date(),
selectType: 'Grocery',
address: {
addressLine1: '123 Test Street',
},
});
we do that all over our apps atm
foolswisdom
foolswisdom•2y ago
okay 🤷
Braveheart
BraveheartOP•2y ago
its not a great ad for solid but still prefer 100x to react
foolswisdom
foolswisdom•2y ago
It works fine for me, don't know what to tell you
Braveheart
BraveheartOP•2y ago
got an example?
foolswisdom
foolswisdom•2y ago
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
foolswisdom
foolswisdom•2y ago
I didn't show it in this example, but inside the callback you can safely access any properties like so mockDataStore().address.addressLine1
Braveheart
BraveheartOP•2y ago
No description
Braveheart
BraveheartOP•2y ago
ah ok ill try
foolswisdom
foolswisdom•2y ago
It's a function
Braveheart
BraveheartOP•2y ago
No description
foolswisdom
foolswisdom•2y ago
Well, yes, a Date object is not a string lol So TS will error Try mockDataStore().date.toDateString()
Braveheart
BraveheartOP•2y ago
i owe you a coffee
No description
Braveheart
BraveheartOP•2y ago
4th time you helped me at least
foolswisdom
foolswisdom•2y ago
Great! 😂 We solved it No problem
Braveheart
BraveheartOP•2y ago
ill pay it back with a youtube vid
foolswisdom
foolswisdom•2y ago
I'm just usually on my phone and it's difficult to spell everything out
Braveheart
BraveheartOP•2y ago
and credit ya
foolswisdom
foolswisdom•2y ago
And write examples
Braveheart
BraveheartOP•2y ago
so <Show when={"date" in mockDataStore && mockDataStore}> is vanilla typescript , or some solid black magic?
foolswisdom
foolswisdom•2y ago
Okay, so "date" in mockDataStore is just a regular javascript check, does this key ('date') exist in the object? And TS knows that if the property is in the object, then it isn't an empty object, so it must be of type StoreType. Now, when you have an expression "date" in mockDataStore && mockDataStore, the && conditional ensures that the expression only resolves to mockDataStore if the first condition passed, which means TS knows that mockDataStore is of type StoreType. If it doesn't pass, then the whole expression simply evaluates to undefined. That's the JS/TS part 👆 Now, you pass this expression to <Show>'s when={}, and solid checks if it is undefined or not. If it is not undefined, then solid passes the value as a function to the callback. Solid also narrows the type (TS) of the value passed to the callback such that TS knows that the value is of type T, not undefined. There's no magic here, just solid doing some type assertions But solid can only do that in callback form
Braveheart
BraveheartOP•2y ago
what should my setters be?
No description
foolswisdom
foolswisdom•2y ago
Hmm that's very interesting, probably something to do with how the TS types for the setter is defined in solid 🤔 You can do setMockDataStore({companyName: e.currentTarget.value}) and TS won't complain Though if you plan on setting properties separately, you might want to consider using createStore<Partial<StoreType>> Which would mean TS would allow some properties to be set while others are not set Which would also solve this problem
Braveheart
BraveheartOP•2y ago
this the only reason I use stores atm) i can't be the first to have the issue with stores any examples of this? this seems to allow single prop updates fine not sure i need anything else how would I use your way to replace this path way? setCompanyDetailsStore('companyDetails', 'companyName', e.currentTarget.value) this works
onChange={(e) => setFormDataStore({ address: { addressLine1: e.currentTarget.value } })}
onChange={(e) => setFormDataStore({ address: { addressLine1: e.currentTarget.value } })}
Want results from more Discord servers?
Add your server