I want to add multiple keys to the dictionary via loop. For example, when I create a key, that key already has its value.
I have the following scenario:
var keys = ['key1', 'key2', 'key3', 'key4']
var dic = {}
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
dic[key] = 'value' + i
}
Note that I am adding several keys and already assigning the value of that key, but it does not work in TypeScript, so I have tested it works perfectly in JavaScript.
This line above has error. Note that I cannot add an element that is not contained in the array:
dic[key] = 'value' + i
Error details
Element implicitly has an 'any' type because expression of type
'string' can't be used to index type '{}'.
How can I get my Array keys and assign it to the dictionary with the loop value?
You need to define the type of dic
Use any
var dic: any = {}
Be more precise
var dic: Record<string, string> = {}
Be even more precise
type Key = 'key1' | 'key2' | 'key3' | 'key4'
var keys: Key[] = ['key1', 'key2', 'key3', 'key4']
var dic: Partial<<Record<Key, string>> = {}
If the keys are static, then you can make it even better (credit to this thread)
const keys = ['key1', 'key2', 'key3', 'key4'] as const; // TS3.4 syntax
type Key = typeof keys[number];
var dic: Partial<Record<Key, string>> = {
"key1": "123"
}
Related
I am building some objects in JavaScript and pushing those objects into an array, I am storing the key I want to use in a variable then creating my objects like so:
var key = "happyCount";
myArray.push( { key : someValueArray } );
but when I try to examine my array of objects for every object the key is "key" instead of the value of the variable key. Is there any way to set the value of the key from a variable?
Fiddle for better explanation:
http://jsfiddle.net/Fr6eY/3/
You need to make the object first, then use [] to set it.
var key = "happyCount";
var obj = {};
obj[key] = someValueArray;
myArray.push(obj);
UPDATE 2021:
Computed property names feature was introduced in ECMAScript 2015 (ES6) that allows you to dynamically compute the names of the object properties in JavaScript object literal notation.
const yourKeyVariable = "happyCount";
const someValueArray= [...];
const obj = {
[yourKeyVariable]: someValueArray,
}
In ES6, you can do like this.
var key = "name";
var person = {[key]:"John"}; // same as var person = {"name" : "John"}
console.log(person); // should print Object { name="John"}
var key = "name";
var person = {[key]:"John"};
console.log(person); // should print Object { name="John"}
Its called Computed Property Names, its implemented using bracket notation( square brackets) []
Example: { [variableName] : someValue }
Starting with ECMAScript 2015, the object initializer syntax also
supports computed property names. That allows you to put an expression
in brackets [], that will be computed and used as the property name.
For ES5, try something like this
var yourObject = {};
yourObject[yourKey] = "yourValue";
console.log(yourObject );
example:
var person = {};
var key = "name";
person[key] /* this is same as person.name */ = "John";
console.log(person); // should print Object { name="John"}
var person = {};
var key = "name";
person[key] /* this is same as person.name */ = "John";
console.log(person); // should print Object { name="John"}
var key = "happyCount";
myArray.push( { [key] : someValueArray } );
Use this.
var key = 'a'
var val = 'b'
console.log({[key]:val})
//a:'b'
In ES6 We can write objects like this
const key= "Name";
const values = "RJK"
const obj = {
[key]: values,
}
In TypeScript, it should look something like this
let title ="Current User";
type User = {
[key:string | number | symbol]: any
};
let myVar: User = {};
myVar[ title ] = "App Developer";
console.log(myVar)// Prints: { Current User:"App Developer"}
let key = "name";
let name= "john";
const obj ={
id:01
}
obj[key] = name;
console.log(obj); // output will {id:01,name:"john}
Use square brackets shown it will set as key
The Reality
The problem in JS is simply that:
{ x: 2 }
is THE SAME as:
{ "x": 2 }
(even if you have x a variable defined!)
Solution
Add square brackets [] around the identifier of the key:
var key = "happyCount";
myArray.push( { [key] : someValueArray } );
(Nowadays the keyword var is not much used, so please use instead const or let)
tldr;
I'm trying to type a custom React hook:
import { useRef } from 'react';
type Reference = [
Promise<unknown>,
(value?: unknown) => void,
(reason?: unknown) => void,
];
const usePromise = () => {
const reference: Reference = [];
const container = useRef(reference);
reference[0] = new Promise((resolve, reject) => {
reference[1] = resolve;
reference[2] = reject;
});
// [promise, resolve, reject]
return container.current;
};
export default usePromise;
TypeScript complains about reference saying:
Type '[]' is not assignable to type 'Reference'.
Source has 0 element(s) but target requires 3.
How can I allow TypeScript to accept the empty array / tuple initialization, too? And also maybe there is a way to give usePromise the type of the value, too, so that it doesn't say unknown?
Edit 2:
If you want to initialize the tuple to an empty array, you can do this:
const reference : [Reference, Reference, Reference] = ([] as unknown) as [Reference, Reference, Reference];
Edit: edited as per OP's comment
You need to do something like this if you want to use a tuple:
Please read the inline comments below.
type Reference = {
name: string;
age: number;
}
//In your case, it should be something like this beause your tuple may have upto 3 values of type Reference.
//initialization
//null! - the '!' mark after null is the non-null assertion operator, which will let you assign null value to a type Reference.
const reference2: [Reference, Reference, Reference] = [null!, null!, null!];
//assignment
reference2[0] = {name: 'John', age:10};
Original Answer:
That is because you have declared a const variable reference which is of type Reference (object instance of a class, type or interface called Reference) and but initializing it with an empty array [ ].
If you want reference to have an array of Reference objects, then you should do this instead:
const reference: Reference[] = [];
If you have strict type checking enabled in your tsconfig, you should do it like this:
const reference: Reference[] = [] as Reference[];
You can read about the as keyword here: Stack Overflow question about the 'as' keyword
The type Reference is a tuple with three entries. So when you assign to a variable of the type Reference, typescript checks if 1) the assigned value is a tuple 2) if the assigned tuple has the desired length 3) if all types of the entries in the tuple match the corresponding types in the Reference type.
You assign an empty list, which violates these conditions. If you don't have strict null checks enabled, you can simply assign const reference: Reference = [null, null, null];
Instead for forcing typescript to ignore your problem, I feel it's better to describe reference as what it really is:
let reference: Reference|null = null;
Or:
type Reference = [
Promise<unknown> | null,
((value?: unknown) => void) | null,
((reason?: unknown) => void) | null,
];
how can I use this type of chaining
let numbers = [20,17,35,4,12]
let evenSquares = numbers.filter{$0 % 2 == 0}.map{$0 * $0}
in such usecase
I have array of objects, I want to filter it by keys of external dictionary and then assign to those filtered objects value of dictionary where object id = dictionary key and then sort result object by dictionary value
here is code I have now:
let scoreDict: [String: Double]
var objects: [Object]
var filteredObjects = objects.filter { scoreDict.keys.contains.contains($0.id.uuidString.lowercased()) }
// .. and what next?
var scoresAssigned = filteredObjects.map { $0.score = scoreDict[$0.id.uuidString.lowercased()] } // This do not compile ""Cannot assign to property: '$0' is immutable"
Assuming Object is a struct, based on the error message...
This just shows that higher-order functions shouldn't be used everywhere. map transforms each element in a sequence into something else. So instead of assigning score, you need to return a new Object with its score changed.
var scoresAssigned = filteredObjects.map { $0.withScore(scoreDict[$0.id.uuidString.lowercased()]) }
withScore will look something like:
func withScore(_ score: Int) -> Object {
var copy = self
copy.score = score
return copy
}
But, if you just want to assign the score a new value, I recommend a simple for loop.
for i in 0..<filteredObjects.count {
filteredObjects[i].score = scoreDict[$0.id.uuidString.lowercased()]
}
Also note that you only need to access the dictionary once. If it's nil, the key doesn't exist.
var filteredObjects = [Object]()
for i in 0..<objects.count {
if let score = scoreDict[$0.id.uuidString.lowercased()] {
objects[i].score = score
filteredObjects.append(objects[i])
}
}
I am building some objects in JavaScript and pushing those objects into an array, I am storing the key I want to use in a variable then creating my objects like so:
var key = "happyCount";
myArray.push( { key : someValueArray } );
but when I try to examine my array of objects for every object the key is "key" instead of the value of the variable key. Is there any way to set the value of the key from a variable?
Fiddle for better explanation:
http://jsfiddle.net/Fr6eY/3/
You need to make the object first, then use [] to set it.
var key = "happyCount";
var obj = {};
obj[key] = someValueArray;
myArray.push(obj);
UPDATE 2021:
Computed property names feature was introduced in ECMAScript 2015 (ES6) that allows you to dynamically compute the names of the object properties in JavaScript object literal notation.
const yourKeyVariable = "happyCount";
const someValueArray= [...];
const obj = {
[yourKeyVariable]: someValueArray,
}
In ES6, you can do like this.
var key = "name";
var person = {[key]:"John"}; // same as var person = {"name" : "John"}
console.log(person); // should print Object { name="John"}
var key = "name";
var person = {[key]:"John"};
console.log(person); // should print Object { name="John"}
Its called Computed Property Names, its implemented using bracket notation( square brackets) []
Example: { [variableName] : someValue }
Starting with ECMAScript 2015, the object initializer syntax also
supports computed property names. That allows you to put an expression
in brackets [], that will be computed and used as the property name.
For ES5, try something like this
var yourObject = {};
yourObject[yourKey] = "yourValue";
console.log(yourObject );
example:
var person = {};
var key = "name";
person[key] /* this is same as person.name */ = "John";
console.log(person); // should print Object { name="John"}
var person = {};
var key = "name";
person[key] /* this is same as person.name */ = "John";
console.log(person); // should print Object { name="John"}
var key = "happyCount";
myArray.push( { [key] : someValueArray } );
Use this.
var key = 'a'
var val = 'b'
console.log({[key]:val})
//a:'b'
In ES6 We can write objects like this
const key= "Name";
const values = "RJK"
const obj = {
[key]: values,
}
In TypeScript, it should look something like this
let title ="Current User";
type User = {
[key:string | number | symbol]: any
};
let myVar: User = {};
myVar[ title ] = "App Developer";
console.log(myVar)// Prints: { Current User:"App Developer"}
let key = "name";
let name= "john";
const obj ={
id:01
}
obj[key] = name;
console.log(obj); // output will {id:01,name:"john}
Use square brackets shown it will set as key
The Reality
The problem in JS is simply that:
{ x: 2 }
is THE SAME as:
{ "x": 2 }
(even if you have x a variable defined!)
Solution
Add square brackets [] around the identifier of the key:
var key = "happyCount";
myArray.push( { [key] : someValueArray } );
(Nowadays the keyword var is not much used, so please use instead const or let)
tldr;
I have an array with data for my TableView sections
let menuItems : Dictionary<String,Dictionary<String,String>>[] = [
[
"data" : [
"name":"test",
"image":"test.png"
]
],
[
"data" : [
"name":"test2",
"image":"test2.png"
]
]
]
I'm trying to access it by using subscript
func tableView(tableView: UITableView!, titleForHeaderInSection section: Int) -> String! {
return menuItems[section]["data"]["name"]
}
and have the error
Could not find member 'subscript'
I have read a lot of similar questions on stackoverflow, but still haven't understood how to fix it. I tried to unwrap with "!" symbol and used another variables - no result.
Could you explain how does it works, please?
println(menuItems[0]["data"]!["name"])
Short answer: menuItems[0]["data"] returns an optional dictionary.
You can look at the below REPL output to understand the issue.
sets up the object.
shows that the array returns a regular dictionary. If the index is out of range, an error will be thrown instead of returning an optional dictionary.
shows that accessing a key in a dictionary that does not exist will return nil
shows that accessing a key in a dictionary will return an optional of its value type. For instance, if a dictionary is storing Strings in its values, it will return a String? when indexed into.
shows that we cannot use subscripts on an optional dictionary.
shows that we can force the optional dictionary to be a dictionary because we know it is not nil. The REPL shows us that the new return type is Dictionary<String, String>
shows that we can then use subscripts to get at the innermost values, and this returns an optional string to us. Optional strings are printable, so my code above doesn't need a second !.
shows that if we force both dictionary return types to their non-optional types, we get a regular value back (a string).
In real code, you would probably want to check for optionals, and handle nils accordingly.
1> let menu: Dictionary<String, Dictionary<String, String>>[] = [["dict1" : ["key" : "val"]], ["dict2" : ["key" : "val"]]]
menu: Dictionary<String, Dictionary<String, String>>[] = size=2 {
[0] = {
[0] = {
key = "dict1"
value = {
[0] = {
key = "key"
value = "val"
}
}
}
}
[1] = {
[0] = {
key = "dict2"
value = {
[0] = {
key = "key"
value = "val"
}
}
}
}
}
2> menu[0]
$R1: Dictionary<String, Dictionary<String, String>> = {
[0] = {
key = "dict1"
value = {
[0] = {
key = "key"
value = "val"
}
}
}
}
3> menu[0]["key"]
$R2: Dictionary<String, String>? = nil
4> menu[0]["dict1"]
$R3: Dictionary<String, String>? = Some {
[0] = {
key = "key"
value = "val"
}
}
5> menu[0]["dict1"]["key"]
REPL:6:1: error: could not find member 'subscript'
menu[0]["dict1"]["key"]
^~~~~~~~~~~~~~~~~~~~~~~
6> menu[0]["dict1"]!
$R4: Dictionary<String, String> = {
[0] = {
key = "key"
value = "val"
}
}
7> menu[0]["dict1"]!["key"]
$R5: String? = "val"
8> menu[0]["dict1"]!["key"]!
$R6: String = "val"