<A, K extends string | symbol>(f: (a: A) => K): (
self: Iterable<A>
) => Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>
<A, K extends string | symbol>(self: Iterable<A>, f: (a: A) => K): Record<
Record.ReadonlyRecord.NonLiteralKey<K>,
NonEmptyArray<A>
>Groups all elements by the string or symbol key returned by f.
Details
Each property in the returned record contains a non-empty array of elements
that produced that key. Unlike group, matching elements do not need to be
consecutive.
Example (Grouping by a key)
import { Iterable } from "effect"
// Group by string length
const words = ["a", "bb", "ccc", "dd", "eee", "f"]
const byLength = Iterable.groupBy(words, (word) => word.length.toString())
console.log(byLength)
// { "1": ["a", "f"], "2": ["bb", "dd"], "3": ["ccc", "eee"] }
// Group by first letter
const names = ["Alice", "Bob", "Charlie", "David", "Anna", "Betty"]
const byFirstLetter = Iterable.groupBy(names, (name) => name[0])
console.log(byFirstLetter)
// { "A": ["Alice", "Anna"], "B": ["Bob", "Betty"], "C": ["Charlie"], "D": ["David"] }
// Group by category
const items = [
{ name: "apple", category: "fruit" },
{ name: "carrot", category: "vegetable" },
{ name: "banana", category: "fruit" },
{ name: "broccoli", category: "vegetable" }
]
const byCategory = Iterable.groupBy(items, (item) => item.category)
console.log(byCategory)
// {
// "fruit": [{ name: "apple", category: "fruit" }, { name: "banana", category: "fruit" }],
// "vegetable": [{ name: "carrot", category: "vegetable" }, { name: "broccoli", category: "vegetable" }]
// }
// Group numbers by even/odd
const numbers = [1, 2, 3, 4, 5, 6]
const evenOdd = Iterable.groupBy(numbers, (n) => n % 2 === 0 ? "even" : "odd")
console.log(evenOdd)
// { "odd": [1, 3, 5], "even": [2, 4, 6] }export const const groupBy: {
<A, K extends string | symbol>(
f: (a: A) => K
): (
self: Iterable<A>
) => Record<
Record.ReadonlyRecord.NonLiteralKey<K>,
NonEmptyArray<A>
>
<A, K extends string | symbol>(
self: Iterable<A>,
f: (a: A) => K
): Record<
Record.ReadonlyRecord.NonLiteralKey<K>,
NonEmptyArray<A>
>
}
Groups all elements by the string or symbol key returned by f.
Details
Each property in the returned record contains a non-empty array of elements
that produced that key. Unlike group, matching elements do not need to be
consecutive.
Example (Grouping by a key)
import { Iterable } from "effect"
// Group by string length
const words = ["a", "bb", "ccc", "dd", "eee", "f"]
const byLength = Iterable.groupBy(words, (word) => word.length.toString())
console.log(byLength)
// { "1": ["a", "f"], "2": ["bb", "dd"], "3": ["ccc", "eee"] }
// Group by first letter
const names = ["Alice", "Bob", "Charlie", "David", "Anna", "Betty"]
const byFirstLetter = Iterable.groupBy(names, (name) => name[0])
console.log(byFirstLetter)
// { "A": ["Alice", "Anna"], "B": ["Bob", "Betty"], "C": ["Charlie"], "D": ["David"] }
// Group by category
const items = [
{ name: "apple", category: "fruit" },
{ name: "carrot", category: "vegetable" },
{ name: "banana", category: "fruit" },
{ name: "broccoli", category: "vegetable" }
]
const byCategory = Iterable.groupBy(items, (item) => item.category)
console.log(byCategory)
// {
// "fruit": [{ name: "apple", category: "fruit" }, { name: "banana", category: "fruit" }],
// "vegetable": [{ name: "carrot", category: "vegetable" }, { name: "broccoli", category: "vegetable" }]
// }
// Group numbers by even/odd
const numbers = [1, 2, 3, 4, 5, 6]
const evenOdd = Iterable.groupBy(numbers, (n) => n % 2 === 0 ? "even" : "odd")
console.log(evenOdd)
// { "odd": [1, 3, 5], "even": [2, 4, 6] }
groupBy: {
<function (type parameter) A in <A, K extends string | symbol>(f: (a: A) => K): (self: Iterable<A>) => Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>A, function (type parameter) K in <A, K extends string | symbol>(f: (a: A) => K): (self: Iterable<A>) => Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>K extends string | symbol>(
f: (a: A) => Kf: (a: Aa: function (type parameter) A in <A, K extends string | symbol>(f: (a: A) => K): (self: Iterable<A>) => Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>A) => function (type parameter) K in <A, K extends string | symbol>(f: (a: A) => K): (self: Iterable<A>) => Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>K
): (self: Iterable<A>self: interface Iterable<T, TReturn = any, TNext = any>Iterable<function (type parameter) A in <A, K extends string | symbol>(f: (a: A) => K): (self: Iterable<A>) => Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>A>) => type Record<K extends keyof any, T> = {
[P in K]: T
}
Construct a type with a set of properties K of type T
Record<import RecordRecord.ReadonlyRecord.type ReadonlyRecord<in out K extends string | symbol, out A>.NonLiteralKey<K extends string | symbol> = K extends string ? Record.ReadonlyRecord.IsFiniteString<K> extends true ? string : K : symbolRepresents a type that converts literal string keys to generic string type and symbol keys to generic symbol type.
This is useful for maintaining type safety while allowing flexible key types in record operations.
Example (Converting literal keys to non-literal keys)
import type { Record } from "effect"
// For literal string keys, this becomes 'string'
type Example1 = Record.ReadonlyRecord.NonLiteralKey<"foo" | "bar"> // string
// For symbol keys, this becomes 'symbol'
type Example2 = Record.ReadonlyRecord.NonLiteralKey<symbol> // symbol
NonLiteralKey<function (type parameter) K in <A, K extends string | symbol>(f: (a: A) => K): (self: Iterable<A>) => Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>K>, type NonEmptyArray<A> = [A, ...A[]]A mutable array guaranteed to have at least one element.
When to use
Use when mutation is acceptable and non-emptiness must be tracked at the type
level.
Details
This is the mutable counterpart of
NonEmptyReadonlyArray
. Most Array
module functions return NonEmptyArray when the result is guaranteed
non-empty.
Example (Typing a mutable non-empty array)
import type { Array } from "effect"
const nonEmpty: Array.NonEmptyArray<number> = [1, 2, 3]
nonEmpty.push(4)
NonEmptyArray<function (type parameter) A in <A, K extends string | symbol>(f: (a: A) => K): (self: Iterable<A>) => Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>A>>
<function (type parameter) A in <A, K extends string | symbol>(self: Iterable<A>, f: (a: A) => K): Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>A, function (type parameter) K in <A, K extends string | symbol>(self: Iterable<A>, f: (a: A) => K): Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>K extends string | symbol>(
self: Iterable<A>self: interface Iterable<T, TReturn = any, TNext = any>Iterable<function (type parameter) A in <A, K extends string | symbol>(self: Iterable<A>, f: (a: A) => K): Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>A>,
f: (a: A) => Kf: (a: Aa: function (type parameter) A in <A, K extends string | symbol>(self: Iterable<A>, f: (a: A) => K): Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>A) => function (type parameter) K in <A, K extends string | symbol>(self: Iterable<A>, f: (a: A) => K): Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>K
): type Record<K extends keyof any, T> = {
[P in K]: T
}
Construct a type with a set of properties K of type T
Record<import RecordRecord.ReadonlyRecord.type ReadonlyRecord<in out K extends string | symbol, out A>.NonLiteralKey<K extends string | symbol> = K extends string ? Record.ReadonlyRecord.IsFiniteString<K> extends true ? string : K : symbolRepresents a type that converts literal string keys to generic string type and symbol keys to generic symbol type.
This is useful for maintaining type safety while allowing flexible key types in record operations.
Example (Converting literal keys to non-literal keys)
import type { Record } from "effect"
// For literal string keys, this becomes 'string'
type Example1 = Record.ReadonlyRecord.NonLiteralKey<"foo" | "bar"> // string
// For symbol keys, this becomes 'symbol'
type Example2 = Record.ReadonlyRecord.NonLiteralKey<symbol> // symbol
NonLiteralKey<function (type parameter) K in <A, K extends string | symbol>(self: Iterable<A>, f: (a: A) => K): Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>K>, type NonEmptyArray<A> = [A, ...A[]]A mutable array guaranteed to have at least one element.
When to use
Use when mutation is acceptable and non-emptiness must be tracked at the type
level.
Details
This is the mutable counterpart of
NonEmptyReadonlyArray
. Most Array
module functions return NonEmptyArray when the result is guaranteed
non-empty.
Example (Typing a mutable non-empty array)
import type { Array } from "effect"
const nonEmpty: Array.NonEmptyArray<number> = [1, 2, 3]
nonEmpty.push(4)
NonEmptyArray<function (type parameter) A in <A, K extends string | symbol>(self: Iterable<A>, f: (a: A) => K): Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>A>>
} = dual<(...args: Array<any>) => any, <A, K extends string | symbol>(self: Iterable<A>, f: (a: A) => K) => Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>>(arity: 2, body: <A, K extends string | symbol>(self: Iterable<A>, f: (a: A) => K) => Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>): ((...args: Array<any>) => any) & (<A, K extends string | symbol>(self: Iterable<A>, f: (a: A) => K) => Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>) (+1 overload)Creates a function that can be called in data-first style or data-last
(pipe-friendly) style.
When to use
Use to expose one implementation through both direct and pipe-friendly
call styles.
Details
Pass either the arity of the uncurried function or a predicate that decides
whether the current call is data-first. Arity is the common case. Use a
predicate when optional arguments make arity ambiguous.
Example (Selecting data-first or data-last style by arity)
import { Function, pipe } from "effect"
const sum = Function.dual<
(that: number) => (self: number) => number,
(self: number, that: number) => number
>(2, (self, that) => self + that)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
Example (Defining overloads with call signatures)
import { Function, pipe } from "effect"
const sum: {
(that: number): (self: number) => number
(self: number, that: number): number
} = Function.dual(2, (self: number, that: number): number => self + that)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
Example (Selecting data-first or data-last style with a predicate)
import { Function, pipe } from "effect"
const sum = Function.dual<
(that: number) => (self: number) => number,
(self: number, that: number) => number
>(
(args) => args.length === 2,
(self, that) => self + that
)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
dual(2, <function (type parameter) A in <A, K extends string | symbol>(self: Iterable<A>, f: (a: A) => K): Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>A, function (type parameter) K in <A, K extends string | symbol>(self: Iterable<A>, f: (a: A) => K): Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>K extends string | symbol>(
self: Iterable<A>self: interface Iterable<T, TReturn = any, TNext = any>Iterable<function (type parameter) A in <A, K extends string | symbol>(self: Iterable<A>, f: (a: A) => K): Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>A>,
f: (a: A) => Kf: (a: Aa: function (type parameter) A in <A, K extends string | symbol>(self: Iterable<A>, f: (a: A) => K): Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>A) => function (type parameter) K in <A, K extends string | symbol>(self: Iterable<A>, f: (a: A) => K): Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>K
): type Record<K extends keyof any, T> = {
[P in K]: T
}
Construct a type with a set of properties K of type T
Record<import RecordRecord.ReadonlyRecord.type ReadonlyRecord<in out K extends string | symbol, out A>.NonLiteralKey<K extends string | symbol> = K extends string ? Record.ReadonlyRecord.IsFiniteString<K> extends true ? string : K : symbolRepresents a type that converts literal string keys to generic string type and symbol keys to generic symbol type.
This is useful for maintaining type safety while allowing flexible key types in record operations.
Example (Converting literal keys to non-literal keys)
import type { Record } from "effect"
// For literal string keys, this becomes 'string'
type Example1 = Record.ReadonlyRecord.NonLiteralKey<"foo" | "bar"> // string
// For symbol keys, this becomes 'symbol'
type Example2 = Record.ReadonlyRecord.NonLiteralKey<symbol> // symbol
NonLiteralKey<function (type parameter) K in <A, K extends string | symbol>(self: Iterable<A>, f: (a: A) => K): Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>K>, type NonEmptyArray<A> = [A, ...A[]]A mutable array guaranteed to have at least one element.
When to use
Use when mutation is acceptable and non-emptiness must be tracked at the type
level.
Details
This is the mutable counterpart of
NonEmptyReadonlyArray
. Most Array
module functions return NonEmptyArray when the result is guaranteed
non-empty.
Example (Typing a mutable non-empty array)
import type { Array } from "effect"
const nonEmpty: Array.NonEmptyArray<number> = [1, 2, 3]
nonEmpty.push(4)
NonEmptyArray<function (type parameter) A in <A, K extends string | symbol>(self: Iterable<A>, f: (a: A) => K): Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>A>> => {
const const out: Record<
string | symbol,
NonEmptyArray<A>
>
out: type Record<K extends keyof any, T> = {
[P in K]: T
}
Construct a type with a set of properties K of type T
Record<string | symbol, type NonEmptyArray<A> = [A, ...A[]]A mutable array guaranteed to have at least one element.
When to use
Use when mutation is acceptable and non-emptiness must be tracked at the type
level.
Details
This is the mutable counterpart of
NonEmptyReadonlyArray
. Most Array
module functions return NonEmptyArray when the result is guaranteed
non-empty.
Example (Typing a mutable non-empty array)
import type { Array } from "effect"
const nonEmpty: Array.NonEmptyArray<number> = [1, 2, 3]
nonEmpty.push(4)
NonEmptyArray<function (type parameter) A in <A, K extends string | symbol>(self: Iterable<A>, f: (a: A) => K): Record<Record.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>A>> = {}
for (const const a: Aa of self: Iterable<A>self) {
const const k: K extends string | symbolk = f: (a: A) => Kf(const a: Aa)
if (var Object: ObjectConstructorProvides functionality common to all JavaScript objects.
Object.ObjectConstructor.hasOwn(o: object, v: PropertyKey): booleanDetermines whether an object has a property with the specified name.
hasOwn(const out: Record<
string | symbol,
NonEmptyArray<A>
>
out, const k: string | symbolk)) {
const out: Record<
string | symbol,
NonEmptyArray<A>
>
out[const k: K extends string | symbolk].Array<A>.push(...items: A[]): numberAppends new elements to the end of an array, and returns the new length of the array.
push(const a: Aa)
} else {
const out: Record<
string | symbol,
NonEmptyArray<A>
>
out[const k: K extends string | symbolk] = [const a: Aa]
}
}
return const out: Record<
string | symbol,
NonEmptyArray<A>
>
out
})