Replace all values in an object with a specific key - javascript

My goal here is to convert all type values in the array below to the types in the object that collerate to numbers.
let obj = [
{
type: 'boolean',
name: 'coolName',
description: 'First description',
required: false
},
{
type: 'subcommand',
name: 'destroy',
description: 'Destroy something',
options: [
{
type:"integer",
name:"amount",
description:"How much would you like to destroy?",
required: true
}
]
}
]
const types = {
'subcommand':1,
'subcommandgroup':2,
'string':3,
'integer':4,
'boolean':5,
'user':6,
'channel':7,
'role':8,
'mentionable':9,
'number':10,
'attachment':11
}
I've been looking for a while and cannot find a function that also iterates through the nested object, if anyone has a way to do this please let me know.

obj.map(o => {
o.type = types[o.type]
if(o.options){
o.options.map(opt => {
opt.type = types[opt.type]
})
}
return o;
})

Related

How to use reduce with typescript to populate a typed array?

I have an array of objects which is populated with objects generated by a reduce loop. These objects already have a type, hence I need the object generated by reduce to have the same type, but I'm strugling with the initial value of the reduce, since it is an empty object.
How can I set a type to the initial object without getting an error saying that the object is missing properties?
Interface and base value:
const productFormLocal = [
{
field: 'id',
config: {
elementType: false,
value: '',
validation: {},
valid: true,
touched: false
}
},
{
field: 'nome',
config: {
elementType: 'input',
elementConfig: {
type: 'text',
placeholder: 'Nome do Produto',
name: 'nome',
},
label: 'Nome do Produto',
value: '',
validation: {
required: true,
},
valid: false,
touched: false
}
}
]
interface ProductsList {
id: number
nome: string
qtde: number
valor: number
valorTotal: number
}
const productsList: ProductsList[] = []
For instance, if I do that I get the reduce working fine, but I wouldn't be able to push the generated objects to the array:
const data: Record<string, any> = {}
const productValues = productFormLocal.reduce((obj, item) => (
obj[item.field] = item.config.value, obj
), data)
productsList.push(productValues)
And if I do that I would get an error saying that data is missing the ProductList properties:
const data: ProductsList = {}
const productValues = productFormLocal.reduce((obj, item) => (
obj[item.field] = item.config.value, obj
), data)
productsList.push(productValues)
How could I solve this? I looked a lot but I coudn't find a way to get this right.
I know I could set all properties of ProductsList as optional, but it doesn't seem to be the best approach.
Set the reduce generic type, which will type the default value as well as the reducer function return type.
const productValues = productFormLocal.reduce<Record<string, any>>((acc, item) => ({
...acc,
[item.field]: item.config.value
}), {})

Searching through array of objects that contain arrays of objects efficiently

I am currently searching through an array of objects that contains an array of objects, the data structure looks like the following:
const category = 'general'
const field = 'rating'
const schema = {
categories: [
{
name: 'general',
label: 'General',
fields: [
{
name: 'id',
label: 'Market Street ID',
type: 'string'
},
{
name: 'rating',
label: 'Rating',
type: 'number'
}
]
},
{
name: 'location',
label: 'Location',
fields: [
{
name: 'search',
label: 'Query Parameters',
type: 'string'
}
]
}
]
}
The expected result is to search through the categories array for a given category name (in this case 'general') and then search through the fields for a given field name (in this case 'rating') and return the type associated with the field. I have achieved this by doing the following:
const type = schema.categories
.filter((cat) => cat.name === category)
.map((cat) => {
const fieldData = cat.fields.find((f) => f.name === field)
return fieldData.type
})
console.log(type[0])
I am wondering if there is a more efficient way to search through the array of objects within an array of objects, possibly with the type not being returned in an array
If you only need the first match, you can use Array#find along with optional chaining.
const category="general",field="rating",schema={categories:[{name:"general",label:"General",fields:[{name:"id",label:"Market Street ID",type:"string"},{name:"rating",label:"Rating",type:"number"}]},{name:"location",label:"Location",fields:[{name:"search",label:"Query Parameters",type:"string"}]}]};
const type = schema.categories.find(cat => cat.name === category)
?.fields.find(f => f.name === field).type;
console.log(type);

Javascript iterate an array with two conditions

I have this array and these values:
const levels = [
{
name: 'first level primary school'
},
{
name: 'second level primary school'
},
{
name: 'first level secondary school'
}
]
const isPrimarySchool = false
const isSecondarySchool = false
And I want to iterate the array and find if there is a string with the word 'primary' or 'secondary' and turn the value of isPrimarySchool or isSecondarySchool to true.
The method that I found to resolve this, is this one:
levels.forEach(level => {
if (
level.name.toLowerCase().includes('primary')
) {
isPrimarySchool = true
}
if (
level.name.toLowerCase().includes('secondary')
) {
this.isSecondarySchool = true
}
})
Is there a better way to resolve this, using lodash or normal javascript?
You could take a function for using with Array#some and hand over the expected value.
const
has = string => o => o.name.includes(string),
levels = [{ name: 'first level primary school' }, { name: 'second level primary school' }, { name: 'first level secondary school' }],
isPrimarySchool = levels.some(has('primary')),
isSecondarySchool = levels.some(has('second'))
console.log(isPrimarySchool);
console.log(isSecondarySchool);
I want to iterate the array and find if there is a string with the
word 'primary' or 'secondary' and turn the value of isPrimarySchool or
isSecondarySchool to true.
Using some() with includes
const levels = [
{
name: 'first level primary school'
},
{
name: 'second level primary school'
},
{
name: 'first level secondary school'
}
]
const isPrimarySchool = levels.some(x=>x.name.toLowerCase().includes('primary'))
const isSecondarySchool = levels.some(x=>x.name.toLowerCase().includes('secondary'))
console.log({isPrimarySchool,isSecondarySchool})
You could use the built-in Array.some() function and some regexp:
isPrimarySchool = levels.some(level => /primary/.exec(level.name));
isSecondarySchool = levels.some(level => /secondary/.exec(level.name));

How to return an array of objects in GraphQL, possibly using the same endpoint as the one that returns a single object?

I am making a GraphQL API where I would be able to retrieve a car object by its id or retrieve all the cars when no parameter is provided.
Using the code below, I am successfully able to retrieve a single car object by supplying id as a parameter.
However, in the case where I would expect an array of objects i.e. when I supply no parameter at all, I get no result on GraphiQL.
schema.js
let cars = [
{ name: "Honda", id: "1" },
{ name: "Toyota", id: "2" },
{ name: "BMW", id: "3" }
];
const CarType = new GraphQLObjectType({
name: "Car",
fields: () => ({
id: { type: GraphQLString },
name: { type: GraphQLString }
})
});
const RootQuery = new GraphQLObjectType({
name: "RootQueryType",
fields: {
cars: {
type: CarType,
args: {
id: { type: GraphQLString }
},
resolve(parent, args) {
if (args.id) {
console.log(cars.find(car => car.id == args.id));
return cars.find(car => car.id == args.id);
}
console.log(cars);
//***Problem Here***
return cars;
}
}
}
});
Test queries and their respective results:
Query 1
{
cars(id:"1"){
name
}
}
Query 1 Response (Success)
{
"data": {
"cars": {
"name": "Honda"
}
}
}
Query 2
{
cars{
name
}
}
Query 2 Response (Fail)
{
"data": {
"cars": {
"name": null
}
}
}
Any help would be much appreciated.
A Car and a List of Cars are effectively two separate types. A field cannot resolve to a single Car object one time, and an array of Car object another.
Your query is returning null for the name because you told it the cars field would resolve to a single object, but it resolved to an array instead. As a result, it's looking for a property called name on the array object and since one doesn't exist, it's returning null.
You can handle this in a couple of different ways. To keep things to one query, you can use filter instead of find and change the type of your query to a List.
cars: {
type: new GraphQLList(CarType), // note the change here
args: {
id: {
type: GraphQLString
},
},
resolve: (parent, args) => {
if (args.id) {
return cars.filter(car => car.id === args.id);
}
return cars;
}
}
Alternatively, you could split this into two separate queries:
cars: {
type: new GraphQLList(CarType),
resolve: (parent, args) => cars,
},
car: {
type: CarType,
args: {
id: {
// example of using GraphQLNonNull to make the id required
type: new GraphQLNonNull(GraphQLString)
},
},
resolve: (parent, args) => cars.find(car => car.id === args.id),
}
Check the docs for more examples and options.

Exclude given objects from array

I have the below array. I am attempting to exclude certain objects from this array in processing.
For example. I would like to exclude the type 'dog' and only use any object that is of type duck.
I'd like to do this using underscore/lodash but will use plain JS if need be.
animals: [
{
type: 'duck',
name: 'quack',
},
{
type: 'duck',
name: 'quieck',
},
{
type: 'dog',
name: 'bark',
},
]
The Underscore/LoDash way, would be just
var result = _.where(animals, {type: 'duck'});
I suppose your array represents variable animals. You can use Array.prototype.filter() function. If you want all ducks:
const animals = [
{ type: 'duck', name: 'quack' },
{ type: 'duck', name: 'quieck' },
{ type: 'dog', name: 'bark' },
];
const ducks = animals.filter(o => o.type === 'duck');
or if you want to exclude all dogs:
const withoutDogs = animals.filter(o => o.type !== 'dog');
I used ES6 syntax. ES5 equivalent would be:
var ducks = animals.filter(function(o) { return o.type === 'duck' });

Categories

Resources