refactor: Add working Nominal types, clarify identifiers

* Use more Nominal types to help with internal code id usage consistency
 * Broke apart StudioHistoricState type

Co-authored-by: Aria <aria.minaei@gmail.com>
This commit is contained in:
Cole Lawrence 2022-04-29 13:00:14 -04:00
parent 9d9fc1680e
commit 1387ce62d2
58 changed files with 647 additions and 299 deletions

View file

@ -25,6 +25,8 @@ enum ValueTypes {
export interface IdentityDerivationProvider {
/**
* @internal
* Future: We could consider using a `Symbol.for("dataverse/IdentityDerivationProvider")` as a key here, similar to
* how {@link Iterable} works for `of`.
*/
readonly $$isIdentityDerivationProvider: true
/**

View file

@ -33,6 +33,11 @@ const cachedSubPathPointersWeakMap = new WeakMap<
* A wrapper type for the type a `Pointer` points to.
*/
export type PointerType<O> = {
/**
* Only accessible via the type system.
* This is a helper for getting the underlying pointer type
* via the type space.
*/
$$__pointer_type: O
}
@ -53,21 +58,28 @@ export type PointerType<O> = {
*
* 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 :)
*
* Potentially, [TypeScript variance annotations in 4.7+](https://devblogs.microsoft.com/typescript/announcing-typescript-4-7-beta/#optional-variance-annotations-for-type-parameters)
* might be able to help us.
*/
export type Pointer<O> = PointerType<O> &
(O extends UnindexableTypesForPointer
? UnindexablePointer
: unknown extends O
? UnindexablePointer
: O extends (infer T)[]
? Pointer<T>[]
: O extends {}
? {
[K in keyof O]-?: Pointer<O[K]>
} /*&
{[K in string | number]: Pointer<K extends keyof O ? O[K] : undefined>}*/
: UnindexablePointer)
// `Exclude<O, undefined>` will remove `undefined` from the first type
// `undefined extends O ? undefined : never` will give us `undefined` if `O` is `... | undefined`
PointerInner<Exclude<O, undefined>, undefined extends O ? undefined : never>
// By separating the `O` (non-undefined) from the `undefined` or `never`, we
// can properly use `O extends ...` to determine the kind of potential value
// without actually discarding optionality information.
type PointerInner<O, Optional> = O extends UnindexableTypesForPointer
? UnindexablePointer
: unknown extends O
? UnindexablePointer
: O extends (infer T)[]
? Pointer<T>[]
: O extends {}
? {
[K in keyof O]-?: Pointer<O[K] | Optional>
}
: UnindexablePointer
const pointerMetaSymbol = Symbol('pointerMeta')

View file

@ -0,0 +1,106 @@
import type {Pointer, UnindexablePointer} from './pointer'
import type {$IntentionalAny} from './types'
const nominal = Symbol()
type Nominal<Name> = string & {[nominal]: Name}
type Key = Nominal<'key'>
type Id = Nominal<'id'>
type IdObject = {
inner: true
}
type KeyObject = {
inner: {
byIds: Partial<Record<Id, IdObject>>
}
}
type NestedNominalThing = {
optional?: true
byKeys: Partial<Record<Key, KeyObject>>
}
interface TypeError<M> {}
type Debug<T extends 0> = T
type IsTrue<T extends true> = T
type IsFalse<F extends false> = F
type IsExtends<F, R extends F> = F
type IsExactly<F, R extends F> = F extends R
? true
: TypeError<[F, 'does not extend', R]>
function test() {
const p = todo<Pointer<NestedNominalThing>>()
const key1 = todo<Key>()
const id1 = todo<Id>()
type A = UnindexablePointer[typeof key1]
type BaseChecks = [
IsExtends<any, any>,
IsExtends<undefined | 1, undefined>,
IsExtends<string, Key>,
IsTrue<IsExactly<UnindexablePointer[typeof key1], Pointer<undefined>>>,
IsTrue<
IsExactly<Pointer<undefined | true>['...']['...'], Pointer<undefined>>
>,
IsTrue<
IsExactly<
Pointer<Record<Key, true | undefined>>[Key],
Pointer<true | undefined>
>
>,
IsTrue<IsExactly<Pointer<undefined>[Key], Pointer<undefined>>>,
// Debug<Pointer<undefined | Record<string, true>>[Key]>,
IsTrue<IsExactly<Pointer<Record<string, true>>[string], Pointer<true>>>,
IsTrue<
IsExactly<
Pointer<undefined | Record<string, true>>[string],
Pointer<true | undefined>
>
>,
IsTrue<
IsExactly<
Pointer<undefined | Record<Key, true>>[Key],
Pointer<true | undefined>
>
>,
// Debug<Pointer<undefined | true>['...']['...']>,
// IsFalse<any extends Pointer<undefined | true> ? true : false>,
// what extends what
IsTrue<1 & undefined extends undefined ? true : false>,
IsFalse<1 | undefined extends undefined ? true : false>,
]
t<Pointer<undefined | true>>() //
.isExactly(p.optional).ok
t<Pointer<undefined | KeyObject>>() //
.isExactly(p.byKeys[key1]).ok
t<Pointer<undefined | KeyObject['inner']>>() //
.isExactly(p.byKeys[key1].inner).ok
t<Pointer<undefined | IdObject>>() //
.isExactly(p.byKeys[key1].inner.byIds[id1]).ok
p.byKeys[key1]
}
function todo<T>(hmm?: TemplateStringsArray): T {
return null as $IntentionalAny
}
function t<T>(): {
isExactly<R extends T>(
hmm: R,
): T extends R
? // any extends R
// ? TypeError<[R, 'is any']>
// :
{ok: true}
: TypeError<[T, 'does not extend', R]>
} {
return {isExactly: (hmm) => hmm as $IntentionalAny}
}