Flow errors out on the property ruleId.
If I hover over action, it displays the right type for the action including the property ruleId.
Is there a reason why Flow barks on me here?
export const ADVANCED_RULES_ADD_NEW_RULE: string = "ADVANCED_RULES_ADD_NEW_RULE";
export type AdvancedRulesAddNewRule = {
type: string,
predicateId: InternalId,
ruleId: InternalId,
direction: Direction
};
export type Action = AdvancedRulesAddNewRule | AnotherAction | SomeOtherAction;
The type seems to be correctly defined, I have no idea why the property ruleId isn't recognized.
Related
I would like to understand if and how it is possible to skip validating parts of a schema in zod?
In the following example, I would like to validate the foo schema to make sure that the object contains a property id of type number and a property data of type array but (maybe cause there is a lot of data) I would like to prevent validating all the actual array entries in data.
import {z} from 'zod';
const foo = z.object({
id: z.number(),
data: z.array(z.string()),
});
This does the job:
const dataItem = z.custom<DataItem>(); // type DataItem defined by you elsewhere
const foo = z.object({
id: z.number(),
data: z.array(dataItem),
});
// { id: string; data: DataItem[] }
https://github.com/colinhacks/zod/discussions/1575
I have this type:
export interface ConnectorForModel {
_type: "connector.for.model",
connectorDefinitionId: string
}
I want to model is as a zod schema. Actually I am using toZod, like this:
export const ConnectorForModelZod: toZod<ConnectorForModel> = z.object({
_type: z.literal("connector.for.model"),
connectorDefinitionId: z.string()
});
And I get this type error:
Type 'ZodLiteral<"connector.for.model">' is not assignable to type 'never'.
Whats the right way to express this?
I think the quickest way to get this working is with ZodType:
import { z } from "zod";
export interface ConnectorForModel {
_type: "connector.for.model";
connectorDefinitionId: string;
}
export const ConnectorForModelZod: z.ZodType<ConnectorForModel> = z.object({
_type: z.literal("connector.for.model"),
connectorDefinitionId: z.string()
});
Aside: I tend to define my types from my zod schemas rather than the other way around. If you don't have control over the type that you're working with then the given approach is the way to go, but you could potentially avoid writing the same code twice using z.TypeOf on the zod schema
type ConnectorForModel = z.TypeOf<typeof ConnectorForModelZod>;
This type would be equivalent to your interface.
Terminating app due to uncaught exception 'RLMException', reason: 'Attempting to modify object outside of a write transaction - call beginWriteTransaction on an RLMRealm instance first.'
All changes to a managed object (addition, modification and deletion) must be done within a write transaction. For example,
// Update an object with a transaction
try! realm.write {
author.name = "Thomas Pynchon"
}
I can make a Realm sub-class conform to ObservableObject. However, I don't see how to make the realm properties updatable in SwiftUI. Realm property example below.
#objc dynamic var myName: String = "Adam"
Realm automagically sets up the schema based on #objc dynamic var. I don't see a way to get #Published on a realm property. SwiftUI will render a TextField, but crashes when the value is edited.
TextField("Quantity (\(shoppingItem.myUnit!.myName))", value: $shoppingItem.stdQty, formatter: basicFormat)
.textFieldStyle(RoundedBorderTextFieldStyle())
.keyboardType(.numbersAndPunctuation)
Is there any way to wrap SwiftUI state changes inside a Realm write transaction?
Another way to do this is to use a Custom Binding, and when setting the property, open a transaction and save data to realm.
TextField("Quantity (\(shoppingItem.myUnit!.myName))",
value: Binding(get: {shoppingItem.stdQty},
set: {(value) in
//if your state property is in a view model, all this code could be like viewModel.saveData(newMessage: value)
let realm = try! Realm()
try! realm.write {
shoppingItem.stdQty = value
}
}),
formatter: basicFormat)
.textFieldStyle(RoundedBorderTextFieldStyle())
.keyboardType(.numbersAndPunctuation)
This will save to realm on every character inserted
Consider the Realm property, stdQty shown below. It can only be changed within a write transaction.
import RealmSwift
import Combine
class ShoppingItems: Object, ObservableObject
let objectWillChange = PassthroughSubject<Void, Never>()
#objc dynamic var stdQty: Double = 1
You cannot bind stdQty without the error in the original question. However you can create a calculated variable that can be bound.
var formQty: Double {
get {
return stdQty
}
set {
objectWillChange.send()
if let sr = self.realm {
try! sr.write {
stdQty = newValue
}
}
}
}
Binding the calculated variable works fine.
TextField("Quantity (\(shoppingItem.myUnit!.myName))", value: $shoppingItem.formQty, formatter: basicFormat)
.textFieldStyle(RoundedBorderTextFieldStyle())
.keyboardType(.numbersAndPunctuation)
Answer limitation: objectWillChange is only triggered by the calculated variable. Changes in the form are reflected in the form. Changes in the realm don't trigger a Combine objectWillChange yet.
I define an multiple subtypes in the Action creator in redux:
Action creator:
export type Action = { type: "SELECT", index: number } | { type: "OTHER" };
Reducer:
module.exports = (state: string = "", action: Action): string => {
switch (action.type) {
case "SELECT":
return action.index;
default:
return state;
}
};
but if I define SELECT in a constant const select = "SELECT" and implement it in the code above I obtain an error message:
property `index`. Property not found in object type
Note: Taking flow-pattern as it is F8 app:
https://github.com/fbsamples/f8app/blob/master/js/actions/types.js
How should implement it by avoiding having "SELECT" keyword both in the action and in the reducer?
You would normally have another constant with the action type, which would be used for both your action and reducer.
const SELECT = 'SELECT';
or even better (to avoid any conflicts):
const SELECT = 'redux/<module>/SELECT';
In the same action file or in another (that's totally up to you). Then just export like export const SELECT, and import like import { SELECT } from './constants'.
You should also take a look at redux-ducks, might be of your interest.
EDIT:
They use bitwise OR to group all possible different action cases. That helps testing whether the code is syntactically correct with flow (by setting their dispatched actions to match type Action). See their full explanation here.
That does not take away the fact that they have to dispatch the action with their desired action type though. login
All the examples I find online for narrowing the disjoint union in flowtype uses string literals, like the official one. I would like to know if there is a way to check against a value from an enum like:
const ACTION_A = 'LITERAL_STRING_A';
const ACTION_B = 'LITERAL_STRING_B';
type ActionA = {
// This is not allowed
type: ACTION_A,
// type: 'LITERAL_STRING_A' is allowed
dataA: ActionAData,
}
type ActionB = {
// This is not allowed
type: ACTION_B,
// type: 'LITERAL_STRING_B' is allowed
dataB: ActionBData,
}
type Action = ActionA | ActionB;
function reducer(state: State, action: Action): State {
// Want to narrow Action to ActionA or ActionB based on type
switch (action.type) {
// case 'LITERAL_STRING_A': -- successfully narrow the type
case ACTION_A: // doesn't work
// action.dataA is accessible
...
}
...
}
Unfortunately you can't do these because strings are ineligible as type annotations.
If there is any other way around this that doesn't force typing the string literals everywhere I would love to know.
If there isn't a way around this, also accept suggestions on a higher level how to not need to define these disjoint sets for redux actions.
I'm not in my best shape right now, so sorry if I read your question wrong. I'll try to help anyway. Is this what you're looking for?
const actionTypes = {
FOO: 'FOO',
BAR: 'BAR'
}
type ActionType = $Keys<actionTypes> // one of FOO, BAR
function buzz(actionType: ActionType) {
switch(actionType) {
case actionTypes.FOO:
// blah
}
This should work. Sorry if my syntax is a bit off.
If you're asking how to avoid listing all action types in type Action = ActionA | ActionB then sorry, I don't know, I think this is the way you do it. If I recall correctly, a slightly nicer syntax for defining long unions was recently introduce in Flow:
type Action =
| ActionA
| ActionB
| ActionC
Also, if you don't need individual action types, you can just do
type Action =
| {type: ACTION_A; dataA: ActionAData;}
| {type: ACTION_B; dataB: ActionBData;}
The better way would be to use string literal types for const values:
Try flow...
const ACTION_A:'LITERAL_STRING_A' = 'LITERAL_STRING_A';
const ACTION_B:'LITERAL_STRING_B' = 'LITERAL_STRING_B';