Standardize handling of non-compound types (#118)

This commit is contained in:
Aria 2022-04-09 15:02:39 +02:00 committed by GitHub
parent 77c7fc969f
commit 16c070b6e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 782 additions and 396 deletions

View file

@ -297,10 +297,16 @@ function isIdentityChangeProvider(
* For pointers, the value is returned by first creating a derivation, so it is
* reactive e.g. when used in a `prism`.
*
* @param pointerOrDerivationOrPlainValue - The argument to return a value from.
* @param input - The argument to return a value from.
*/
export const val = <P>(
pointerOrDerivationOrPlainValue: P,
export const val = <
P extends
| PointerType<$IntentionalAny>
| IDerivation<$IntentionalAny>
| undefined
| null,
>(
input: P,
): P extends PointerType<infer T>
? T
: P extends IDerivation<infer T>
@ -308,13 +314,11 @@ export const val = <P>(
: P extends undefined | null
? P
: unknown => {
if (isPointer(pointerOrDerivationOrPlainValue)) {
return valueDerivation(
pointerOrDerivationOrPlainValue,
).getValue() as $IntentionalAny
} else if (isDerivation(pointerOrDerivationOrPlainValue)) {
return pointerOrDerivationOrPlainValue.getValue() as $IntentionalAny
if (isPointer(input)) {
return valueDerivation(input).getValue() as $IntentionalAny
} else if (isDerivation(input)) {
return input.getValue() as $IntentionalAny
} else {
return pointerOrDerivationOrPlainValue as $IntentionalAny
return input as $IntentionalAny
}
}

View file

@ -17,6 +17,6 @@ export {default as iterateAndCountTicks} from './derivations/iterateAndCountTick
export {default as iterateOver} from './derivations/iterateOver'
export {default as prism} from './derivations/prism/prism'
export {default as pointer, getPointerParts, isPointer} from './pointer'
export type {Pointer, PointerType} from './pointer'
export type {Pointer, PointerType, OpaqueToPointers} from './pointer'
export {default as Ticker} from './Ticker'
export {default as PointerProxy} from './PointerProxy'

View file

@ -7,6 +7,10 @@ type PointerMeta = {
path: (string | number)[]
}
const symbolForUnpointableTypes = Symbol()
export type OpaqueToPointers = {[symbolForUnpointableTypes]: true}
export type UnindexableTypesForPointer =
| number
| string
@ -15,6 +19,7 @@ export type UnindexableTypesForPointer =
| void
| undefined
| Function // eslint-disable-line @typescript-eslint/ban-types
| OpaqueToPointers
export type UnindexablePointer = {
[K in $IntentionalAny]: Pointer<undefined>
@ -34,6 +39,19 @@ export type PointerType<O> = {
* explanation of pointers.
*
* @see Atom
*
* @remarks
* The Pointer type is quite tricky because it doesn't play well with `any` and other inexact types.
* Here is an example that one would expect to work, but currently doesn't:
* ```ts
* declare function expectAnyPointer(pointer: Pointer<any>): void
*
* expectAnyPointer(null as Pointer<{}>) // doesn't work
* ```
*
* The current solution is to just avoid using `any` with pointer-related code (or type-test it well).
* But if you enjoy solving typescript puzzles, consider fixing this :)
*
*/
export type Pointer<O> = PointerType<O> &
(O extends UnindexableTypesForPointer