-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #81 from ahrjarrett/@ahrjarrett/v0.40.10
feat: adds `Widen`
- Loading branch information
Showing
6 changed files
with
192 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"any-ts": patch | ||
--- | ||
|
||
feat: adds `Widen` type + ambient namespace |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -60,3 +60,5 @@ export { | |
Focus, | ||
type FocusConstructor | ||
} from "./lens/focus" | ||
|
||
export type { Widen } from "./widen/exports" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export type { Widen } from "./widen" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
import type { Widen } from "./widen" | ||
import type { expect, assert } from "../test/exports" | ||
|
||
declare namespace Spec { | ||
|
||
type __Widen__ = [ | ||
// ^? | ||
expect<assert.equal< | ||
Widen<[1, [2, [3, [4, [5, [6]]]]]], 0>, | ||
[1, [2, [3, [4, [5, [6]]]]]] | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<[1, [2, [3, [4, [5, [6]]]]]], 1>, | ||
[number, [2, [3, [4, [5, [6]]]]]] | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<[1, [2, [3, [4, [5, [6]]]]]], 2>, | ||
[number, [number, [3, [4, [5, [6]]]]]] | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<[1, [2, [3, [4, [5, [6]]]]]], 3>, | ||
[number, [number, [number, [4, [5, [6]]]]]] | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<[1, [2, [3, [4, [5, [6]]]]]], 4>, | ||
[number, [number, [number, [number, [5, [6]]]]]] | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<[1, [2, [3, [4, [5, [6]]]]]], 5>, | ||
[number, [number, [number, [number, [number, [6]]]]]] | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<[1, [2, [3, [4, [5, [6]]]]]], 6>, | ||
[number, [number, [number, [number, [number, [number]]]]]] | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<{ abc: 1, def: { ghi: 2, jkl: { mno: 3, pqr: { stu: 4, vwx: { yz: 5 } } } } }, 0>, | ||
{ abc: 1, def: { ghi: 2, jkl: { mno: 3, pqr: { stu: 4, vwx: { yz: 5 } } } } } | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<{ abc: 1, def: { ghi: 2, jkl: { mno: 3, pqr: { stu: 4, vwx: { yz: 5 } } } } }, 1>, | ||
{ abc: number, def: { ghi: 2, jkl: { mno: 3, pqr: { stu: 4, vwx: { yz: 5 } } } } } | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<{ abc: 1, def: { ghi: 2, jkl: { mno: 3, pqr: { stu: 4, vwx: { yz: 5 } } } } }, 2>, | ||
{ abc: number, def: { ghi: number, jkl: { mno: 3, pqr: { stu: 4, vwx: { yz: 5 } } } } } | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<{ abc: 1, def: { ghi: 2, jkl: { mno: 3, pqr: { stu: 4, vwx: { yz: 5 } } } } }, 3>, | ||
{ abc: number, def: { ghi: number, jkl: { mno: number, pqr: { stu: 4, vwx: { yz: 5 } } } } } | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<{ abc: 1, def: { ghi: 2, jkl: { mno: 3, pqr: { stu: 4, vwx: { yz: 5 } } } } }, 4>, | ||
{ abc: number, def: { ghi: number, jkl: { mno: number, pqr: { stu: number, vwx: { yz: 5 } } } } } | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<{ abc: 1, def: { ghi: 2, jkl: { mno: 3, pqr: { stu: 4, vwx: { yz: 5 } } } } }, 5>, | ||
{ abc: number, def: { ghi: number, jkl: { mno: number, pqr: { stu: number, vwx: { yz: number } } } } } | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<{ abc: [1, def: { ghi: [2, jkl: { mno: [3, pqr: { stu: [4, vwx: { yz: [5] }] }] }] }] }, 0>, | ||
{ abc: [1, { ghi: [2, { mno: [3, pqr: { stu: [4, vwx: { yz: [5] }] }] }] }] } | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<{ abc: [1, def: { ghi: [2, jkl: { mno: [3, pqr: { stu: [4, vwx: { yz: [5] }] }] }] }] }, 1>, | ||
{ abc: [1, { ghi: [2, { mno: [3, pqr: { stu: [4, vwx: { yz: [5] }] }] }] }] } | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<{ abc: [1, def: { ghi: [2, jkl: { mno: [3, pqr: { stu: [4, vwx: { yz: [5] }] }] }] }] }, 2>, | ||
{ abc: [number, { ghi: [2, { mno: [3, pqr: { stu: [4, vwx: { yz: [5] }] }] }] }] } | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<{ abc: [1, def: { ghi: [2, jkl: { mno: [3, pqr: { stu: [4, vwx: { yz: [5] }] }] }] }] }, 3>, | ||
{ abc: [number, { ghi: [2, { mno: [3, pqr: { stu: [4, vwx: { yz: [5] }] }] }] }] } | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<{ abc: [1, def: { ghi: [2, jkl: { mno: [3, pqr: { stu: [4, vwx: { yz: [5] }] }] }] }] }, 4>, | ||
{ abc: [number, { ghi: [number, { mno: [3, pqr: { stu: [4, vwx: { yz: [5] }] }] }] }] } | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<{ abc: [1, def: { ghi: [2, jkl: { mno: [3, pqr: { stu: [4, vwx: { yz: [5] }] }] }] }] }, 5>, | ||
{ abc: [number, { ghi: [number, { mno: [3, pqr: { stu: [4, vwx: { yz: [5] }] }] }] }] } | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<{ abc: [1, def: { ghi: [2, jkl: { mno: [3, pqr: { stu: [4, vwx: { yz: [5] }] }] }] }] }, 6>, | ||
{ abc: [number, { ghi: [number, { mno: [number, pqr: { stu: [4, vwx: { yz: [5] }] }] }] }] } | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<{ abc: [1, def: { ghi: [2, jkl: { mno: [3, pqr: { stu: [4, vwx: { yz: [5] }] }] }] }] }, 7>, | ||
{ abc: [number, { ghi: [number, { mno: [number, pqr: { stu: [4, vwx: { yz: [5] }] }] }] }] } | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<{ abc: [1, def: { ghi: [2, jkl: { mno: [3, pqr: { stu: [4, vwx: { yz: [5] }] }] }] }] }, 8>, | ||
{ abc: [number, { ghi: [number, { mno: [number, pqr: { stu: [number, vwx: { yz: [5] }] }] }] }] } | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<{ abc: [1, def: { ghi: [2, jkl: { mno: [3, pqr: { stu: [4, vwx: { yz: [5] }] }] }] }] }, 9>, | ||
{ abc: [number, { ghi: [number, { mno: [number, pqr: { stu: [number, vwx: { yz: [5] }] }] }] }] } | ||
>>, | ||
|
||
expect<assert.equal< | ||
Widen<{ abc: [1, def: { ghi: [2, jkl: { mno: [3, pqr: { stu: [4, vwx: { yz: [5] }] }] }] }] }, 10>, | ||
{ abc: [number, { ghi: [number, { mno: [number, pqr: { stu: [number, vwx: { yz: [number] }] }] }] }] } | ||
>>, | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import type { any } from "../any/exports" | ||
import type { nonempty } from "../empty" | ||
|
||
/** | ||
* {@link Widen `Widen`} is a type constructor that accepts a tree and an optional max depth | ||
* (default to `2`), and constructs a new tree with the same overall structure. | ||
* | ||
* Until it hits its max depth, any leaf it encounters is widened to the least upper bound of | ||
* its respective domain. | ||
* | ||
* For example: | ||
* | ||
* - given `{ abc: ["def", "ghi"] }`, {@link Widen `Widen`} returns `{ abc: [string, string] }`; | ||
* - given `[{ abc: 123 }, { def: 456 }]`, {@link Widen `Widen`} returns `[{ abc: number }, { def: number }]` | ||
* | ||
* @example | ||
* import type { Widen } from "any-ts" | ||
* | ||
* type StateTuple<S> = readonly [state: S, setState: S | ((s: S) => S)] | ||
* declare function useState<const state>(initialState: Widen<state, 3>): StateTuple<Widen<state, 3>> | ||
* | ||
* const [state] = useState([ | ||
* { user: { first: "Caril Ann", last: "Fugate", email: "[email protected]" } }, | ||
* { user: { first: "Charles", last: "Starkweather", email: "[email protected]" } } | ||
* ]) | ||
* | ||
* state | ||
* // ^? [{ user: { first: string, last: string, email: string } }, { user: { first: string, last: string, email: string } }] | ||
*/ | ||
export type Widen<type, maxDepth extends number = 2> = Widen.tree<type, maxDepth> | ||
|
||
export declare namespace Widen { | ||
type leaf<type> = type extends { valueOf(): infer target } ? target : type | ||
type tree<type, maxDepth extends number> = internal.widen<type, [], maxDepth> | ||
} | ||
|
||
declare namespace internal { | ||
type widen<type, depth extends void[], maxDepth extends number> | ||
= type extends any.primitive ? Widen.leaf<type> | ||
: [depth[`length`], maxDepth] extends [maxDepth, depth[`length`]] ? type | ||
: type extends any.array ? internal.widenAll<type, [], depth, maxDepth> | ||
: { -readonly [k in keyof type]: internal.widen<type[k], [...depth, void], maxDepth> } | ||
|
||
type widenAll< | ||
xs extends any.array, | ||
acc extends any.array, | ||
depth extends void[], | ||
maxDepth extends number, | ||
> = [depth[`length`], maxDepth] extends [maxDepth, depth[`length`]] ? xs | ||
: xs extends nonempty.array<infer head, infer tail> | ||
? internal.widen<head, [...depth, void], maxDepth> extends infer x | ||
? widenAll<tail, [...acc, x], depth, maxDepth> | ||
: never | ||
: acc | ||
} |