TypeScript object Array type definition - arrays

What is the difference between this two type definitions?
type objectArray = [object]
type objectArray = object[]

[object] is a tuple. It's the type of an array with a single value in it, and the value must be an object.
object[] is the same as Array<object>. It's the type of an array with any number of values, where any such values must be object.
All tuples are arrays, but a tuple is a more restrictive type of array, with a specified number of elements.

Related

How to create an Array for Tuples in Scala?

Im trying to create an empty Array to store coordinates of an object in an Tuple which is then stored in an Array.
When I try:
var walls = Array[Tuple2]()
Im getting this error message:
kinds of the type arguments (Tuple2) do not conform to the expected kinds of the type parameters (type T).
[error] Tuple2's type parameters do not match type T's expected parameters:
[error] class Tuple2 has two type parameters, but type T has none
[error] var walls = Array[Tuple2]()
Is there any possibility to do this?
Tuple2 is a type constructor (of kind [*, *] => *).
Array is a type constructor too (of kind [*] => *).
You have to apply Tuple2 to two types (of kind *) in order to make it suitable as an argument of Array.
That's why Array[(Int, Int)] aka Array[Tuple2[Int, Int]] is working while Array[Tuple2] is not.
Okay I found a way:
var walls = Array[(Int, Int)]()

How to declare an array of type of a variable in Typescript?

Suppose I have a variable x, which can be any type:
let x: number = 5
I want to create an array which stores values of type x. In this case I want a number[].
However, x can be any type: primitives, objects, custom types, etc.
I'm looking for something like this:
// Doesn't work
let arr: <x>[] = []
I feel like generics is somehow the answer here, but I can't think of any concrete way to solve this.
Is there any way to achieve this?
If x is a type name, you just use x[] or Array<x>. Handbook link
If x is a variable name or similar, you use the typeof type operator: (typeof x)[] or Array<typeof x>:
declare let x: number;
let arr1: Array<typeof x>;
// ^^^−−−−−−−−−−−− this is number[]
let arr2: (typeof x)[];
// ^^^−−−−−−−−−−−− so is this
Playground Link
Note that the TypeScript typeof operator is not the same as the JavaScript typeof operator for values. When typeof appears as part of a type definition, it's the TypeScript typeof type operator; when it appears in relation to a value, it's the JavaScript typeof operator.

Reducing a Swift array to [Int:Int?] with nil initializer is empty

Why does reducing an array into a hash with the keys as array values and the value as nil give an empty result?
[1,2,3].reduce(into: [Int:Int?](), { $0[$1] = nil })
[1,2,3].reduce(into: [Int:Int?](), { $0[$1] = 1 })
Both of these should have 3 entries, right?
In Swift, setting a dictionary value to nil like you did in the question removes that value from the dictionary entirely. However there are some odd caveats to this.
In your example, you use a Dictionary with type [Int:Int?]:
var dictionary: [Int:Int?] = [1: 1, 2: 1, 3: 1]
Setting a value to nil in the following way removes it:
dictionary[1] = nil
Setting a value to nil with type Int? will assign nil instead:
dictionary[1] = nil as Int?
Likewise, using the updateValue(_:forKey:) function will do the same:
dictionary.updateValue(nil, forKey: 1)
Printing the dictionary after performing either of these operations would show the following:
[1: nil, 2: Optional(1), 3: Optional(1)]
So the behavior is a bit odd but it is possible to achieve your intended result. I don't really recommend it because of how unnatural it is; it is possible, though.
The behaviour is not at all odd actually, and it's a really natural outcome if you understand some fundamental features of Swift's dictionaries and optionals.
Nested optionals
Firstly, optionals are composable. You can have nested optionals, like Optional<Optional<Int>> (a.k.a. Int??). A nested optional like this has possible three values. To illustrate their difference, imagine the result of array.first, where array has type Array<Optional<Optional<Int>>:
Optional.some(Optional.some(someWrappedValue)), which is just the "non-nil" case, with a payload of someWrappedValue. In the context of array.first, that means the array is non-empty, and the first element is non-nil value someWrappedValue (of type Int).
Optional.some(Optional.none), which is a non-nil optional containing a nil. In the context of array.first, that means ten array is non-empty, and the first element is itself nil.
Optional.none, which is just a nil optional. In the context of array.first, that means the array is empty, and there is no first element.
Note the different between case 2 and case 3. "Where" the nil is "found" along the chain has a semantic difference. Optional.none (a.k.a. nil) means there are no elements, which is semantically different to Optional.some(Optional.none), which means there are elements, but the first of them is actually nil.
The precise meaning of nil
Secondly, nil is a shorthand for Optional<T>.none, where T is inferred from the context. For example, that's why let x = nil is illegal, because the type inference system has no clues as to what value of T is appropriate.
Note that nil on its own is inferred to a none at the "earliest" ("outermost") level of optionality. (Case 3, in the list above)
Assign nil through a dictionary subscript
Thirdly, assigning nil to a Dictionary through a subscript erases the value for the given key.
Putting it together
Given these three points, we can consider your example. The subscript of a dictionary is "one layer more optional" than the Value generic type of the dictionary. E.g. for a dict of type [Int: Int], the return type of the subscript operator is V?, and correspondingly, you can assign Int?.
Now consider your dictionary, of type [Int: Int?]. The subscript takes/returns an Int??. Let's consider the three possible cases in context, as before:
Assigning a value of type Optional.some(Optional.some(someWrappedValue)) makes the dict store a value of someWrappedValue for the key, as an Int?. This is what's happening when you write $0[$1] = 1 (Swift is implicitly promoting 1 to Optional.some(Optional.some(1)).
Assigning a value of type Optional.some(Optional.none) makes the dict store a value of nil for the key, as an Int?. This is the part you were missing.
Assigning a value of type Optional.none makes the dict erase any value that might have existed for the key. This is what's happening when you write $0[$1] = nil
So to make this code give your designed outcome, you need to supply a value of the second type. You can do this with:
[1,2,3].reduce(into: [Int:Int?]()) { $0[$1] = Optional.some(nil) }

Understanding syntax for an array of tuples in Swift

I'm trying to understand syntax for arrays of tuples in Swift:
If I create a tuple:
var gameScore: (points: Int, player: String)
I can assign values like this:
gameScore = (1700, "Lisa")
And create an array of this tuple:
var gameScores = [gameScore]
I can append to the array this way:
gameScores.append((1650, "Bart"))
And this way:
gameScore = (1600, "Maggie")
gameScores += [gameScore]
But not this way:
gameScores += [(1600, "Maggie")]
Playground error is:
Playground execution failed: error: Tuples Playground.playground:38:1: error: cannot convert value of type '[(points: Int, player: String)]' to expected argument type 'inout _'
gameScores += [(1600, "Maggie")]
However, this way works:
gameScores += [(points: 1600, player: "Maggie")]
Yes – I have code above that will work, but I'm trying to figure out what I'm not understanding in the failing syntax. Elements don't need to be named for the .append() method, but they need to be named for += [()].
The Swift type inference system is being stretched to the point of breaking here. Swift is having trouble inferring the type of [(1600, "Maggie")] in your example. If you give it a little more information, your example will compile:
gameScores += [(1600, "Maggie") as (points: Int, player: String)]
gameScores += [(1600, "Maggie")] as [(points: Int, player: String)]
and
gameScores = gameScores + [(1600, "Maggie")]
all compile.
It seems Swift is having trouble inferring the type when += is involved.
Looking at the definition of +=:
func +=<C : Collection>(lhs: inout Array<C.Iterator.Element>, rhs: C)
shows that the types of the lhs and rhs are different. Swift is having trouble reconciling the types of the lhs and the rhs from the information given. It seems to be starting with the rhs and then concludes that the type of the lefthand side is inout _ and it tries to reconcile that with the type of gameScores which is [(points: Int, player: String)]. Should it be able to infer the types? Perhaps, but in this case, since you have an easy workaround, I say give the compiler a break and give it the explicit type information and make its job easier:
gameScores += [(points: 1600, player: "Maggie")]

Cannot assign to "" in "self" - Working with Tuples in Swift

I have to classes: FirstViewController and PlanGenerator.
PlanGenerator has a method called getPlanForIndex (day:Int) -> ([PlanElement], [PlanElement])?. It is returning two different Arrays, both containing Object of Plan Element.
getPlanForIndex (day:Int) -> ([PlanElement], [PlanElement])? {
// Do some work and fill arrays
return (firstArray, secondArray)
}
In the FirstViewController I've created two Properties:
let plan:[PlanElement] = [PlanElement]()
let planGen:PlanGenerator = PlanGenerator()
FirstViewControllerhas a method called:
func prepareView () {
plan = planGen.getPlanForIndex(dayIndex)
}
But when I want to call this, I get the error message:
Cannot assign to 'plan' in 'self'
First, your plan member is a constant (declared with let), and you're assigning to it outside of init. If you want to assign to it after initialization, it needs to be declared with var.
Also, your getPlanForIndex returns a tuple, and you're assigning it to a member of singular (not tuple) type. If you want to assign one part of a tuple only, do it like this:
(plan, _) = planGen.getPlanForIndex(dayIndex)
That assigns a tuple to a tuple, satisfying the compiler, but discards the second element.
If you instead want plan to be a tuple, you'll have to declare and initialize it as such. Looks from the comments like you figured out a way to do that, but here's a way with minimal typing (in either sense of the word):
var plan: ([PlanElement], [PlanElement]) = ([], [])
(Once you've declared the type of array, [] is understood to be an empty array of that type. Just var plan = ([], []) leaves the type ambiguous.)

Resources