How to dynamically extend or compose a Yup schema - reactjs

Say I have a Yup.string() to begin with.
Then, at some point, like in a loop, I wanna add required rule to it, effectively:
Yup.string().required('This field is required').
And maybe then add some .email check too.
I have tried this way but didn't seem to work:
function validationSchemaConstructor(question) {
const schema = Yup.string();
question.validation_rules.forEach(rule => {
if ("is_required" in rule) {
schema.required("Hey man nice shot");
}
});
return schema;
}

Ah my mistake- I need to assign the schema again cuz chaining in general works by returning the object again:
function validationSchemaConstructor(question) {
let schema = Yup.string();
question.validation_rules.forEach(rule => {
if ("is_required" in rule) {
schema = schema.required("Hey man nice shot"); // mistake here!
}
});
// un-comment to test dynamically adding additional rule
// schema = schema.email("email plesss");
return schema;
}
Though not sure if I should use the clone() somewhere.
Please advice if there's a better way :)

Related

Laravel Checking if Array or Collection is not Empty to run

I have an object of $person as below:
$person = Person::where('id', $id)->first();
According to which $person exists or not I load other data:
if($person) {
$person->family_members = FamilyMemberController::FamilyMemberOf($person->id);
} else {
$person->family_members = [];
}
In the view file, I check the $person->family_members if not empty and exists to add a generated value :
if(!empty(array_filter($person->family_members))) {
// my code
}
But it throws an error:
array_filter(): Argument #1 ($array) must be of type array, Illuminate\Database\Eloquent\Collection given
I need to check this $person->family_members to make sure whether it's an array or a collection is not empty.
Writing code for if array do something if collection do something is the wrong way of implementation.
You can do two things.
use both returns as collection()
or either use both returns as an array[]
If collection
else {
$person->family_members = collect();
}
If array
use ->toArray() at the end of Eloquent. Check this answer
As well, I think you are confused with array_filter(). Maybe you are searching for in_array() or contains()
Use count method
if(count($person->family_members)>0){
//your code
}
We don't know your code, but given the error, it's safe to assume your method returns a Collection. You can see available methods in the docs. However, if you need it as array, all you need to do is call ->toArray() on the result Collection. Then you can use array_filter.
What about just doing
if(!$person->family_members){
// your code here
}
or
if($person->family_members){
// your code here
} else {
// code of "if it's empty" goes here
}
You can use the count() function to return a count of an index. ex
if(count($person->family_members)){
//do your true algo
}
Why you are using the empty method ?! Try this:
$person->family_members = $person ? FamilyMemberController::FamilyMemberOf($person->id) : null;
if($person->family_members){ // your code }
Try simple ways in Programming ;)

How to fix "expected call-signature to have a typedef" error

I have a switch case function inside my render JSX element that I am using in another const value based on the return values.
I tried looking for a solution to my issue online but none of the answers I found are helping my issue, even after trying them on my code.
function carouselClass(transitionTypeValue: any) {
switch(transitionTypeValue) {
//Different cases and their return values
}
}
const classes = xyz(carouselClass(transitionType)) //Sample of where I'm using my switch function
The code runs fine on Typescript side but I get a linting error which says "typedef expected call-signature: 'carouselClass' to have a typedef"
I tried my best to give enough context, please let me know if more is required as this is my first time posting a question.
Linter giving 'Missing Type definition' warning. Check this out-
https://github.com/palantir/tslint/blob/master/src/rules/typedefRule.ts for details.
Solution: You need to specify the return type for function explicitly
function carouselClass(transitionTypeValue: any):any {
switch(transitionTypeValue) {
//Different cases and their return values
}
}
I think you should add return type if you are calling function and returning something.
function carouselClass(transitionTypeValue: any):any {
switch(transitionTypeValue) {
//Different cases and their return values
}
}
const classes = xyz(carouselClass(transitionType))
You should avoid using type any where ever you can.
Avoid returning any or value with multiple types,
but if you still want to return multiple types of value, try to find similarity and create Enum type or Wrapper Interface, or you can try to create generic function.
interface IClassType extend IClassA, IClassB {}
function carouselClass(transitionTypeValue: any): IClassType {
switch(transitionTypeValue) {
// Different cases and their return values
// Avoid returning multiple types,
// but if you still want to return multiple types of value,
// try to find similarity and create Enum type or Wrapper Interface
}
}
const classes: xyz<IClassType> = xyz(carouselClass(transitionType))

Convert gql function to string with inserted variables

I have this query defined, and use it succesfully in my app:
export const GET_TEAM = gql`
query($id: ID!) {
getTeam(id: $id) {
...CompleteTeam
}
}
${fragments.team}
`
But would like to use it for mocking purpose, and for that I need this representation:
getTeam(id: 3) {
id
name
isActivated
}
Is there any easy way to call gql with variables to accomplish?
There are suggestions how to do this with an instance of ApolloClient. But if possible I'd rather skip involvning the client as I will only mock the resulting data.
To follow up a bit here: The gql function returns a GraphQL Document AST (a parsed tree representation of the query). ASTs are much easier to work with than strings - at least when it gets more complicated.
For your question in the comment: Once you are in the AST space you can do all sorts of transforms. This can be done for example using the visitor patter. GraphQL.js also comes with a visit function that allows you to replace nodes. This code should serve as inspiration, no guarantees that it works ;)
function valueToNode(value) {
if (typeof value === 'string') {
return { kind: 'StringValue', value };
} else if (typeof value === 'number' && Number.isInteger(value)) {
// return integer value node
}
// all other value nodes...
}
visit(ast, {
VariableNode: {
enter(node) {
return valueToNode(variables[node.name.value]);
}
}
}
I am not sure if you should leave the AST space but as described in the comment you can use the printer as mentioned in the comment. Not sure if it prints things that are not documents.

Variable 'Foo' used before declaration. Two classes interdependence

Please, help me solve the problem.
"no-use-before-declare" in tslint.json is true. And I am not allowed to change it.
The problem is following - "variable 'foo' used before declaration" build error.
The code may be simplified to:
export class One {
toSecond() : Two {
return new Two();
}
}
export class Two {
toFirst() : One {
return new One();
}
}
Could it be hacked somehow to overcome the linter warning and have the same result. Any workaround?
You could do:
let Two_forward: typeofTwo;
export class One {
toSecond() : Two {
return new Two_forward();
}
}
export class Two {
toFirst() : One {
return new One();
}
}
// Work around https://github.com/palantir/tslint/issues/3655
type typeofTwo = typeof Two;
Two_forward = Two;
but IMO this is unreasonable compared to just suppressing the lint error with // tslint:disable-next-line:no-use-before-declare. (And it might need further changes if the strictLocalInitialization option proposed here becomes part of strict.)
This was previously filed as a bug on tslint and the resolution was that classes are not hoisted and cannot be used before declaration. The rule is correct in this case.

Variable array/object in one file changes when you change it in a callback in another file

I have two files in Node.js where one requires the other one.
variable_test.js:
TEST = require('./variable_test_external.js');
TEST.get(function(myVariable) {
var changeMeVariable;
console.log(myVariable);
changeMeVariable = myVariable.epicVariable;
changeMeVariable.evenEpicerVariable = "test3";
TEST.get(function(myVariable2) {
console.log(myVariable2);
});
});
variable_test_external.js:
var testVariable = new Array({epicVariable: {evenEpicerVariable: "test1"}}, {epicVariable: {evenEpicerVariable: "test2"}});
exports.get = function(callback) {
callback(testVariable[1]); // I know that the return is unnecessary in this example but in my real application I have return there for compactness.
}
This is the output when run in Node.js with node variable_test.js:
{ epicVariable: { evenEpicerVariable: 'test2' } }
{ epicVariable: { evenEpicerVariable: 'test3' } }
The console.log(myVariable) changes in the two TEST.get's. Why does this happen?
This is a reference copy, not a value copy. You got the object from the array, NOT a copy of them.
changeMeVariable = myVariable.epicVariable;
This would have to fix yout problem
// PSEUDO CODE, i don't know the correct syntax
changeMeVariable = {
epicVariable = myVariable.epicVariable
};
The answer in my case is the following based on the links at the bottom:
changeMeVariable = JSON.parse(JSON.stringify(myVariable.epicVariable));
But, it's much better to manually copy it like the bottom most link like this:
changeMeVariable = {
evenEpicerVariable: myVariable.epicVariable.evenEpicerVariable
}
n0m's answer is similar but if the epicVariable.evenEpicerVariable contained an object that object's reference would still be linked! (I tested it)
References:
What is the most efficient way to deep clone an object in JavaScript?
http://jsperf.com/cloning-an-object/3

Resources