-
Notifications
You must be signed in to change notification settings - Fork 10
Repetitions
ts-macros has repetitions which are heavily inspired by Rust. They allow you to repeat code for every element of an array. Since ts-macros is limited by the typescript compiler, this is the syntax for repetitions:
+[separator?, [arrays], (...params) => codeToRepeat]
The separator
is an optional string that will separate all the expressions generated by the repetition. If a separator is omitted, then every expression will be an ExpressionStatement
.
[arrays]
is an array of array literals. The elements in the arrays are the things the repetition will go through. This is the simplest repetition:
function $test(...numbers: Array<number>) {
+[[numbers, ["a", "b", "c"]], (num: number|string) => console.log(num)]
}
$test!(1, 2, 3);
console.log(1)
console.log(2)
console.log(3)
console.log("a")
console.log("b")
console.log("c")
The repetition goes through all the numbers and strings and creates a console.log
expression for each of them.
Let's say you want to go through 2 or more arrays at the same time, to create combinations like 1a
, 2b
, etc. You can accomplish this by adding another parameter:
function $test(...numbers: Array<number>) {
+[[numbers, ["a", "b", "c"]], (firstArr: number, secondArr: string) => console.log(firstArr + secondArr)]
}
$test!(1, 2, 3);
console.log("1a")
console.log("2b")
console.log("3c")
The second parameter tells the transformer to separate the second array from the rest. So firstArr
goes through all arrays except the second array (["a", "b", "c"]
), and in this case, the two arrays just get separated. But what if we add a third array?
function $test(...numbers: Array<number>) {
+[[numbers, ["a", "b", "c"], ["e", "d", "f"]], (all: number, secondArr: string) => console.log(firstArr + secondArr)]
}
$test!(1, 2, 3);
console.log("1a")
console.log("2b")
console.log("3c")
console.log("e" + null)
console.log("d" + null)
console.log("f" + null)
Here firstArr
goes through the first array and the third array, and secondArr
goes through the second. The second array only has 3 elements, and so it's null
for the elements of the third array.
You can use the following separators:
-
+
- Adds all the values. -
-
- Subtracts all the values. -
*
- Multiplies all the values. -
.
- Creates a property / element access chain from the values. -
[]
- Puts all the values in an array. -
{}
- Creates an object literal from the values. For this separator to work, the result of the repetition callback must be an array literal with 2 elements, the key and the value ([key, value]
). -
()
- Creates a comma list expression from all expressions. -
||
- Creates an OR chain with the expressions. -
&&
- Creates an AND chain with the expressions.
If a repetition is placed inside of a function call, and a separator is not provided, then all results will be passed as arguments.
function $log(...items: Array<number>) {
console.log(+[[items], (item: number) => item + 1]);
}
$log!(1, 2, 3, 4, 5);
console.log(2, 3, 4, 5, 6);
ts-macros provides a built-in macro, $$i
if used inside a repetition, it'll return the number of the current iteration if it's used outside, -1
.
import { $$i } from "../../dist";
function $arr(...els: Array<number>) : Array<number> {
return +["[]", [els], (el: number) => el + $$i!()] as unknown as Array<number>;
}
$arr!(1, 2, 3);
[1, 3, 5]