How to pass value to property that name was passed in function parameter in TypeScript? - node.js

I'm getting eslint/typescript error:
errorUnsafe member access .value on an any value
#typescript-eslint/no-unsafe-member-access
while i try to save value to dynamic property name:
selectChange(name: string, value: string) {
if(this[name] && typeof this[name].value === "string") {
this[name].value = value
}
}
I add if-statement, but it doesn't help, is it possible to do it in proper way ? Or i have to change eslint configuration file.

Ok, i have solution:
declare in some place above:
type column = 'property1' | 'property2'
and remove unnecesary if-statement from method:
selectChange(name: column, value: string) {
this[name].value = value
}
And it will be working perfectly.

Related

Terraform test for null or false value of object key

Hopefully a relatively straightforward one. I have an object that uses the experimental optional attrs feature.
This means that one of the object attributes/keys do not need to be present. I then need to test for either null or false value of said object key in object composition with for loop.
When using the module_variable_optional_attrs experiment, it seems that if you use lookup() to find an object key which does not exist it'll always return null, not the default, as you might expect it to.
I now am having to test with a conditional (lookup(connection, "auto_accept", false) == false || lookup(connection, "auto_accept", false) == null)
this doesn't seem very clean. looking for suggestions on improvements.
EDIT
main.tf
terraform {
# Optional attributes and the defaults function are
# both experimental, so we must opt in to the experiment.
experiments = [module_variable_optional_attrs]
}
variable "example_var" {
type = list(object({
name = string
auto_accept = optional(bool)
}))
description = "Some variable"
default = [{
name = "example-name"
}]
}
Below commands are run from terraform console
> lookup(var.example_var[0], "auto_accept")
false
# now lets make the key undefined
> lookup(var.example_var[0], "auto_accept")
tobool(null)
> lookup(var.example_var[0], "auto_accept", false)
tobool(null)
> tobool(null)
null
I have been in a similar scenario where I had following input map:
payload = {
name = "SomeTestName"
optional_attr = "SomeOptionalAttribue"
}
The above payload could have following possible inputs:
payload = {
name = "SomeTestName"
optional_attr = "SomeOptionalAttribue"
}
OR
payload = {
name = "SomeTestName"
}
OR
payload = {
name = "SomeTestName"
optional_attr = null
}
My use case is to look for optional_attr in the payload and take its value as key and get corresponding value from the following map. If optional_attr is null or not provided then I take default value of mydefault key from the following map:
master_data = {
optional_attr_value1 = "value1"
optional_attr_value2 = "value2"
mydefault = "default_value"
}
Following combination of lookup with null check worked for me:
value = lookup(master_data, can(coalesce(payload.optional_attr)) ? lookup(tomap(payload), "optional_attr", "mydefault") : "mydefault" , "default_value")
What above code does is first it checks if optional_attr is not provided at all in the payload or its provided with a value of null. If this is true then the ternary statement returns false and "mydefault" value is provided that is used by outside lookup function to get mydefault key's corresponding value from master_data. If ternary operator returns true (optional_attry is provided with a value) then the internal lookup function is triggered and it will return value from master_data corresponding to whatever key provided as a value of optional_attr. Again if optional_attr value does not match any key in the master_data then default key of my_default is returned by internal lookup function.

Proper way to parse environment variables

I am using node-config in basically all my projects and most of the time I come across the problem of parsing booleans and numbers which are set as environment variables.
E.g.
default.js
module.exports = {
myNumber = 10,
myBool = true
}
custom-environment-variables.js
module.exports = {
myNumber = "MY_NUMBER",
myBool = "MY_BOOL"
}
Now, the obvious problem is that if I override the default values with custom values set as environment variables they will be a string value instead of a number or boolean value. So now, to make sure in my code that the types are correct. I always have to do type conversion and for booleans use a proper library e.g. yn. The problem is I have to do this conversion every time I use config.get() for example +config.get("myNumber") or yn(config.get("myBool")).
Is there a better and more elegant way to do this?
One solution I see would be to add a type property to an environment variable as it is done here with format. This would allow to do something like this...
custom-environment-variables.js
module.exports = {
myNumber = {
name: "MY_NUMBER",
type: "number"
},
myBool = {
name: "MY_BOOL",
type: "boolean"
}
}
node-config would handle the type conversions and there would be no need to do it all the time in the code when getting it. Of course there would be the requirement to implement a proper parser for booleans but those already exist and could be used here.
By default, environment variables will be parsed as string.
In node-config, we could override this behaviour with __format as shown below.
We don't need any additional libraries. Normal json datatypes like boolean, number, nested json etc., should work well.
Taking an easy to relate example.
config/default.json
{
"service": {
"autostart": false
}
}
custom-environment-variables.json
{
"service": {
"autostart": {
"__name": "AUTOSTART",
"__format": "json"
}
}
}
Now we can pass environment variables when we like to override and no type conversation should be needed for basic types.
This feature is now supported in node-config v3.3.2, see changelog
I use this method:
const toBoolean = (dataStr) => {
return !!(dataStr?.toLowerCase?.() === 'true' || dataStr === true);
};
You can add cases if you want 0 to resolve to true as well:
const toBoolean = (dataStr) => {
return !!(dataStr?.toLowerCase?.() === 'true' || dataStr === true || Number.parseInt(dataStr, 10) === 0);
};

How to assign an index signature to a object's value?

Giving the following code:
export function objToStr(object: object): string {
let str = [];
for (let p in object) {
if (object.hasOwnProperty(p)) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(object[p]))
}
}
return str.join("&")
}
I get the error from object[p]:
Element implicitly has an 'any' type because type '{}' has no index signature. [7017]
I tried with
encodeURIComponent((<any>object[p]))
encodeURIComponent(object[p]: any)
But I still get the error. I find typing everything quite confusing, there is so much types out there.
If someone can tell me what Typescript wants from me there, it would help a lot, it's the last error message and then I'm done switching my code form JS to TS.
EDIT
I had to add "noImplicitAny": true to test the setting as I wasn't sure what is was doing and how the code would react to it.
Turning it to false I now get:
Argument of type 'string' is not assignable to parameter of type 'never'. [2345] for the part insite str.push
Error appears because you have compilerOptions.noImplicitAny = true at tsconfig.json. As error suggests, add index signature to object variable:
let object: { [index: string]: any } = {};
let str: string[] = [];
i.e. any will be specified explicit.

Initializer for conditional binding must have Optional type, not 'String' Variable Error

Hello i have array and i want to explode 1 item into it and i want to check if variable not null or null and gives me that error
Initializer for conditional binding must have Optional type, not 'String' Variable Error
My codes here.
var myStringArrctakesf = itemListcomming.components(separatedBy: ",")
if let commingtel = myStringArrctakesf[11] {
//notnull
} else {
//null
}
I want if myStringArrctakesf[11] is null dont crash app and if not null show variable.
Thanks
components(separatedBy: ) never contain nil in any of its element. Perhaps what you want is to check the myStringArrctakesf has at least 12 elements?
if myStringArrctakesf.count >= 12 {
let comingtel = myStringArrctakesf[11]
} else {
// Array didn't have enough components
}

How to use dot(.) to MongoDB(Mongoose) schema as a parameter [duplicate]

It's difficult to explain the case by words, let me give an example:
var myObj = {
'name': 'Umut',
'age' : 34
};
var prop = 'name';
var value = 'Onur';
myObj[name] = value; // This does not work
eval('myObj.' + name) = value; //Bad coding ;)
How can I set a variable property with variable value in a JavaScript object?
myObj[prop] = value;
That should work. You mixed up the name of the variable and its value. But indexing an object with strings to get at its properties works fine in JavaScript.
myObj.name=value
or
myObj['name']=value (Quotes are required)
Both of these are interchangeable.
Edit: I'm guessing you meant myObj[prop] = value, instead of myObj[name] = value. Second syntax works fine: http://jsfiddle.net/waitinforatrain/dNjvb/1/
You can get the property the same way as you set it.
foo = {
bar: "value"
}
You set the value
foo["bar"] = "baz";
To get the value
foo["bar"]
will return "baz".
You could also create something that would be similar to a value object (vo);
SomeModelClassNameVO.js;
function SomeModelClassNameVO(name,id) {
this.name = name;
this.id = id;
}
Than you can just do;
var someModelClassNameVO = new someModelClassNameVO('name',1);
console.log(someModelClassNameVO.name);
simple as this
myObj.name = value;
When you create an object myObj as you have, think of it more like a dictionary. In this case, it has two keys, name, and age.
You can access these dictionaries in two ways:
Like an array (e.g. myObj[name]); or
Like a property (e.g. myObj.name); do note that some properties are reserved, so the first method is preferred.
You should be able to access it as a property without any problems. However, to access it as an array, you'll need to treat the key like a string.
myObj["name"]
Otherwise, javascript will assume that name is a variable, and since you haven't created a variable called name, it won't be able to access the key you're expecting.
You could do the following:
var currentObj = {
name: 'Umut',
age : 34
};
var newValues = {
name: 'Onur',
}
Option 1:
currentObj = Object.assign(currentObj, newValues);
Option 2:
currentObj = {...currentObj, ...newValues};
Option 3:
Object.keys(newValues).forEach(key => {
currentObj[key] = newValues[key];
});

Resources