-
Notifications
You must be signed in to change notification settings - Fork 12
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]