-
-
Notifications
You must be signed in to change notification settings - Fork 230
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Preserve Array.modify
and Array.modifyOption
non emptiness
#3496
Preserve Array.modify
and Array.modifyOption
non emptiness
#3496
Conversation
🦋 Changeset detectedLatest commit: da5813e The changes in this PR will be included in the next version bump. This PR includes changesets to release 31 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
I'm looking at the doc generation issue. There seems to be a real issue with the way the parameter function passed to Array.modify is now inferred. |
packages/effect/src/Array.ts
Outdated
@@ -1097,6 +1097,8 @@ export const replaceOption: { | |||
<A, B>(self: Iterable<A>, i: number, b: B): Option<Array<A | B>> => modifyOption(self, i, () => b) | |||
) | |||
|
|||
type TypeOfIterable<T extends Iterable<any>> = T extends Iterable<infer A> ? A : never |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is how I fixed the inference of a
. Tell me if:
- it's a valid way to fix the issue
- it's the correct place to put this kind of the type helpers (or if it already exists somewhere. I did not find anything on my own)
you can use i.e. /**
* Apply a function to the element at the specified index, creating a new `Array`,
* or return a copy of the input if the index is out of bounds.
*
* @example
* import { Array } from "effect"
*
* const numbers = [1, 2, 3, 4]
* const result = Array.modify(numbers, 2, (n) => n * 2)
* assert.deepStrictEqual(result, [1, 2, 6, 4])
*
* @since 2.0.0
*/
export const modify: {
<A, B, S extends Iterable<A> = Iterable<A>>(
i: number,
f: (a: ReadonlyArray.Infer<S>) => B
): (self: S) => ReadonlyArray.With<S, ReadonlyArray.Infer<S> | B>
<A, B, S extends Iterable<A> = Iterable<A>>(
self: S,
i: number,
f: (a: ReadonlyArray.Infer<S>) => B
): ReadonlyArray.With<S, ReadonlyArray.Infer<S> | B>
} = dual(
3,
<A, B>(self: Iterable<A>, i: number, f: (a: A) => B): Array<A | B> =>
O.getOrElse(modifyOption(self, i, f), () => Array.from(self))
)
/**
* Apply a function to the element at the specified index, creating a new `Array`,
* or return `None` if the index is out of bounds.
*
* @example
* import { Array, Option } from "effect"
*
* const numbers = [1, 2, 3, 4]
* const result = Array.modifyOption(numbers, 2, (n) => n * 2)
* assert.deepStrictEqual(result, Option.some([1, 2, 6, 4]))
*
* const outOfBoundsResult = Array.modifyOption(numbers, 5, (n) => n * 2)
* assert.deepStrictEqual(outOfBoundsResult, Option.none())
*
* @since 2.0.0
*/
export const modifyOption: {
<A, B, S extends Iterable<A> = Iterable<A>>(
i: number,
f: (a: ReadonlyArray.Infer<S>) => B
): (self: S) => Option<ReadonlyArray.With<S, ReadonlyArray.Infer<S> | B>>
<A, B, S extends Iterable<A> = Iterable<A>>(
self: S,
i: number,
f: (a: ReadonlyArray.Infer<S>) => B
): Option<ReadonlyArray.With<S, ReadonlyArray.Infer<S> | B>>
} = dual(3, <A, B>(self: Iterable<A>, i: number, f: (a: A) => B): Option<Array<A | B>> => {
const out = Array.from(self)
if (isOutOfBound(i, out)) {
return O.none()
}
const next = f(out[i])
// @ts-expect-error
out[i] = next
return O.some(out)
}) tested against // -------------------------------------------------------------------------------------
// modify
// -------------------------------------------------------------------------------------
// $ExpectType string[]
Array.modify([], 0, (
_n // $ExpectType never
) => "a")
// $ExpectType (string | number)[]
Array.modify(numbers, 0, (
_n // $ExpectType number
) => "a")
// $ExpectType [number | "a", ...(number | "a")[]]
Array.modify(nonEmptyNumbers, 0, (
_n // $ExpectType number
) => "a" as const)
// $ExpectType ("a" | 1 | 2)[]
Array.modify(new Set([1, 2] as const), 0, (
_n // $ExpectType 1 | 2
) => "a" as const)
// $ExpectType string[]
pipe(
[],
Array.modify(0, (
_n // $ExpectType never
) => "a")
)
// $ExpectType (string | number)[]
pipe(
numbers,
Array.modify(0, (
_n // $ExpectType number
) => "a")
)
// $ExpectType [number | "a", ...(number | "a")[]]
pipe(
nonEmptyNumbers,
Array.modify(0, (
_n // $ExpectType number
) => "a" as const)
)
// $ExpectType ("a" | 1 | 2)[]
pipe(
new Set([1, 2] as const),
Array.modify(0, (
_n // $ExpectType 1 | 2
) => "a" as const)
)
// -------------------------------------------------------------------------------------
// modifyOption
// -------------------------------------------------------------------------------------
// $ExpectType Option<string[]>
Array.modifyOption([], 0, (
_n // $ExpectType never
) => "a")
// $ExpectType Option<(string | number)[]>
Array.modifyOption(numbers, 0, (
_n // $ExpectType number
) => "a")
// $ExpectType Option<[number | "a", ...(number | "a")[]]>
Array.modifyOption(nonEmptyNumbers, 0, (
_n // $ExpectType number
) => "a" as const)
// $ExpectType Option<("a" | 1 | 2)[]>
Array.modifyOption(new Set([1, 2] as const), 0, (
_n // $ExpectType 1 | 2
) => "a" as const)
// $ExpectType Option<string[]>
pipe(
[],
Array.modifyOption(0, (
_n // $ExpectType never
) => "a")
)
// $ExpectType Option<(string | number)[]>
pipe(
numbers,
Array.modifyOption(0, (
_n // $ExpectType number
) => "a")
)
// $ExpectType Option<[number | "a", ...(number | "a")[]]>
pipe(
nonEmptyNumbers,
Array.modifyOption(0, (
_n // $ExpectType number
) => "a" as const)
)
// $ExpectType Option<("a" | 1 | 2)[]>
pipe(
new Set([1, 2] as const),
Array.modifyOption(0, (
_n // $ExpectType 1 | 2
) => "a" as const)
) |
I did the changes. Thanks for the review! |
not all of them actually, take a closer look at the source code here #3496 (comment) |
@gcanti Why do you think it's needed? As |
@gcanti My bad, I did not run the dtslint job. It's annoying that it's not visible in Vscode. |
It is if you install the eslint plugin |
Ah no apologies I thought you were referring to an eslint error, no unfortunately dtslint is separate |
Type
Description
Same as #3491 but for modify functions
Related