Default to pointer type being never instead of object
This commit is contained in:
parent
754306aca3
commit
036d42a73a
|
@ -2,9 +2,10 @@ import { Encoder } from "./encoder";
|
|||
import { Tag } from "./constants";
|
||||
import { AsPreserve, PreserveOn } from "./symbols";
|
||||
import { DefaultPointer, Value } from "./values";
|
||||
import { is, isAnnotated, IsPreservesAnnotated } from './is';
|
||||
import { is, isAnnotated, IsPreservesAnnotated } from "./is";
|
||||
import { stringify } from "./text";
|
||||
|
||||
export class Annotated<T extends object = DefaultPointer> {
|
||||
export class Annotated<T = DefaultPointer> {
|
||||
readonly annotations: Array<Value<T>>;
|
||||
readonly item: Value<T>;
|
||||
|
||||
|
@ -40,20 +41,20 @@ export class Annotated<T extends object = DefaultPointer> {
|
|||
}
|
||||
|
||||
asPreservesText(): string {
|
||||
const anns = this.annotations.map((a) => '@' + a.asPreservesText()).join(' ');
|
||||
return (anns ? anns + ' ' : anns) + this.item.asPreservesText();
|
||||
const anns = this.annotations.map((a) => '@' + stringify(a)).join(' ');
|
||||
return (anns ? anns + ' ' : anns) + stringify(this.item);
|
||||
}
|
||||
|
||||
get [IsPreservesAnnotated](): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
static isAnnotated<T extends object = DefaultPointer>(x: any): x is Annotated<T> {
|
||||
static isAnnotated<T = DefaultPointer>(x: any): x is Annotated<T> {
|
||||
return isAnnotated(x);
|
||||
}
|
||||
}
|
||||
|
||||
export function annotate<T extends object = DefaultPointer>(v0: Value<T>, ...anns: Value<T>[]): Annotated<T> {
|
||||
export function annotate<T = DefaultPointer>(v0: Value<T>, ...anns: Value<T>[]): Annotated<T> {
|
||||
const v = Annotated.isAnnotated<T>(v0) ? v0 : new Annotated(v0);
|
||||
anns.forEach((a) => v.annotations.push(a));
|
||||
return v;
|
||||
|
|
|
@ -126,7 +126,7 @@ export class Bytes implements Preservable<never> {
|
|||
return this.asPreservesText();
|
||||
}
|
||||
|
||||
[AsPreserve]<T extends object = DefaultPointer>(): Value<T> {
|
||||
[AsPreserve]<T = DefaultPointer>(): Value<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,12 +7,12 @@ import { Record } from "./record";
|
|||
import { Bytes, BytesLike, underlying } from "./bytes";
|
||||
import { Value } from "./values";
|
||||
|
||||
export interface DecoderOptions<T extends object> {
|
||||
export interface DecoderOptions<T> {
|
||||
includeAnnotations?: boolean;
|
||||
decodePointer?: (v: Value<T>) => T;
|
||||
}
|
||||
|
||||
export class Decoder<T extends object> {
|
||||
export class Decoder<T> {
|
||||
packet: Uint8Array;
|
||||
index: number;
|
||||
options: DecoderOptions<T>;
|
||||
|
@ -82,7 +82,7 @@ export class Decoder<T extends object> {
|
|||
return this.includeAnnotations ? new Annotated(v) : v;
|
||||
}
|
||||
|
||||
static dictionaryFromArray<T extends object>(vs: Value<T>[]): Dictionary<Value<T>, T> {
|
||||
static dictionaryFromArray<T>(vs: Value<T>[]): Dictionary<Value<T>, T> {
|
||||
const d = new Dictionary<Value<T>, T>();
|
||||
if (vs.length % 2) throw new DecodeError("Missing dictionary value");
|
||||
for (let i = 0; i < vs.length; i += 2) {
|
||||
|
@ -162,10 +162,10 @@ export class Decoder<T extends object> {
|
|||
}
|
||||
}
|
||||
|
||||
export function decode<T extends object>(bs: BytesLike, options?: DecoderOptions<T>) {
|
||||
export function decode<T>(bs: BytesLike, options?: DecoderOptions<T>) {
|
||||
return new Decoder(bs, options).next();
|
||||
}
|
||||
|
||||
export function decodeWithAnnotations<T extends object>(bs: BytesLike, options: DecoderOptions<T> = {}): Annotated<T> {
|
||||
export function decodeWithAnnotations<T>(bs: BytesLike, options: DecoderOptions<T> = {}): Annotated<T> {
|
||||
return decode(bs, { ... options, includeAnnotations: true }) as Annotated<T>;
|
||||
}
|
||||
|
|
|
@ -10,12 +10,12 @@ import { fromJS } from "./fromjs";
|
|||
export type DictionaryType = 'Dictionary' | 'Set';
|
||||
export const DictionaryType = Symbol.for('DictionaryType');
|
||||
|
||||
export class KeyedDictionary<K extends Value<T>, V, T extends object = DefaultPointer> extends FlexMap<K, V> {
|
||||
export class KeyedDictionary<K extends Value<T>, V, T = DefaultPointer> extends FlexMap<K, V> {
|
||||
get [DictionaryType](): DictionaryType {
|
||||
return 'Dictionary';
|
||||
}
|
||||
|
||||
static isKeyedDictionary<K extends Value<T>, V, T extends object = DefaultPointer>(x: any): x is KeyedDictionary<K, V, T> {
|
||||
static isKeyedDictionary<K extends Value<T>, V, T = DefaultPointer>(x: any): x is KeyedDictionary<K, V, T> {
|
||||
return x?.[DictionaryType] === 'Dictionary';
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ export class KeyedDictionary<K extends Value<T>, V, T extends object = DefaultPo
|
|||
super(canonicalString, items);
|
||||
}
|
||||
|
||||
mapEntries<W, S extends Value<R>, R extends object = DefaultPointer>(f: (entry: [K, V]) => [S, W]): KeyedDictionary<S, W, R> {
|
||||
mapEntries<W, S extends Value<R>, R = DefaultPointer>(f: (entry: [K, V]) => [S, W]): KeyedDictionary<S, W, R> {
|
||||
const result = new KeyedDictionary<S, W, R>();
|
||||
for (let oldEntry of this.entries()) {
|
||||
const newEntry = f(oldEntry);
|
||||
|
@ -37,7 +37,7 @@ export class KeyedDictionary<K extends Value<T>, V, T extends object = DefaultPo
|
|||
asPreservesText(): string {
|
||||
return '{' +
|
||||
Array.from(_iterMap(this.entries(), ([k, v]) =>
|
||||
k.asPreservesText() + ': ' + stringify(v))).join(', ') +
|
||||
stringify(k) + ': ' + stringify(v))).join(', ') +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
@ -74,12 +74,12 @@ export class KeyedDictionary<K extends Value<T>, V, T extends object = DefaultPo
|
|||
}
|
||||
}
|
||||
|
||||
export class Dictionary<V, T extends object = DefaultPointer> extends KeyedDictionary<Value<T>, V, T> {
|
||||
static isDictionary<V, T extends object = DefaultPointer>(x: any): x is Dictionary<V, T> {
|
||||
export class Dictionary<V, T = DefaultPointer> extends KeyedDictionary<Value<T>, V, T> {
|
||||
static isDictionary<V, T = DefaultPointer>(x: any): x is Dictionary<V, T> {
|
||||
return x?.[DictionaryType] === 'Dictionary';
|
||||
}
|
||||
|
||||
static fromJS<V extends object = DefaultPointer, T extends object = DefaultPointer>(x: object): Dictionary<Value<V>, T> {
|
||||
static fromJS<V = DefaultPointer, T = DefaultPointer>(x: object): Dictionary<Value<V>, T> {
|
||||
if (Dictionary.isDictionary<Value<V>, T>(x)) return x as Dictionary<Value<V>, T>;
|
||||
const d = new Dictionary<Value<V>, T>();
|
||||
Object.entries(x).forEach(([key, value]) => d.set(key, fromJS(value)));
|
||||
|
@ -87,12 +87,12 @@ export class Dictionary<V, T extends object = DefaultPointer> extends KeyedDicti
|
|||
}
|
||||
}
|
||||
|
||||
export class KeyedSet<K extends Value<T>, T extends object = DefaultPointer> extends FlexSet<K> {
|
||||
export class KeyedSet<K extends Value<T>, T = DefaultPointer> extends FlexSet<K> {
|
||||
get [DictionaryType](): DictionaryType {
|
||||
return 'Set';
|
||||
}
|
||||
|
||||
static isKeyedSet<K extends Value<T>, T extends object = DefaultPointer>(x: any): x is KeyedSet<K, T> {
|
||||
static isKeyedSet<K extends Value<T>, T = DefaultPointer>(x: any): x is KeyedSet<K, T> {
|
||||
return x?.[DictionaryType] === 'Set';
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ export class KeyedSet<K extends Value<T>, T extends object = DefaultPointer> ext
|
|||
super(canonicalString, items);
|
||||
}
|
||||
|
||||
map<S extends Value<R>, R extends object = DefaultPointer>(f: (value: K) => S): KeyedSet<S, R> {
|
||||
map<S extends Value<R>, R = DefaultPointer>(f: (value: K) => S): KeyedSet<S, R> {
|
||||
return new KeyedSet(_iterMap(this[Symbol.iterator](), f));
|
||||
}
|
||||
|
||||
|
@ -116,12 +116,12 @@ export class KeyedSet<K extends Value<T>, T extends object = DefaultPointer> ext
|
|||
|
||||
asPreservesText(): string {
|
||||
return '#{' +
|
||||
Array.from(_iterMap(this.values(), v => v.asPreservesText())).join(', ') +
|
||||
Array.from(_iterMap(this.values(), stringify)).join(', ') +
|
||||
'}';
|
||||
}
|
||||
|
||||
clone(): Set<T> {
|
||||
return new Set(this);
|
||||
clone(): KeyedSet<K, T> {
|
||||
return new KeyedSet(this);
|
||||
}
|
||||
|
||||
get [Symbol.toStringTag]() { return 'Set'; }
|
||||
|
@ -137,8 +137,8 @@ export class KeyedSet<K extends Value<T>, T extends object = DefaultPointer> ext
|
|||
}
|
||||
}
|
||||
|
||||
export class Set<T extends object = DefaultPointer> extends KeyedSet<Value<T>, T> {
|
||||
static isSet<T extends object = DefaultPointer>(x: any): x is Set<T> {
|
||||
export class Set<T = DefaultPointer> extends KeyedSet<Value<T>, T> {
|
||||
static isSet<T = DefaultPointer>(x: any): x is Set<T> {
|
||||
return x?.[DictionaryType] === 'Set';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,18 +5,18 @@ import { PreserveOn } from "./symbols";
|
|||
import { EncodeError } from "./codec";
|
||||
import { Record, Tuple } from "./record";
|
||||
|
||||
export type Encodable<T extends object> =
|
||||
export type Encodable<T> =
|
||||
Value<T> | Preservable<T> | Iterable<Value<T>> | ArrayBufferView;
|
||||
|
||||
export interface Preservable<T extends object> {
|
||||
export interface Preservable<T> {
|
||||
[PreserveOn](encoder: Encoder<T>): void;
|
||||
}
|
||||
|
||||
export function isPreservable<T extends object>(v: any): v is Preservable<T> {
|
||||
export function isPreservable<T>(v: any): v is Preservable<T> {
|
||||
return typeof v === 'object' && v !== null && typeof v[PreserveOn] === 'function';
|
||||
}
|
||||
|
||||
export interface EncoderOptions<T extends object> {
|
||||
export interface EncoderOptions<T> {
|
||||
canonical?: boolean;
|
||||
includeAnnotations?: boolean;
|
||||
encodePointer?: (v: T) => Value<T>;
|
||||
|
@ -30,7 +30,7 @@ function isIterable<T>(v: any): v is Iterable<T> {
|
|||
return typeof v === 'object' && v !== null && typeof v[Symbol.iterator] === 'function';
|
||||
}
|
||||
|
||||
export class Encoder<T extends object> {
|
||||
export class Encoder<T> {
|
||||
chunks: Array<Uint8Array>;
|
||||
view: DataView;
|
||||
index: number;
|
||||
|
@ -191,13 +191,13 @@ export class Encoder<T extends object> {
|
|||
}
|
||||
}
|
||||
|
||||
export function encode<T extends object>(v: Encodable<T>, options?: EncoderOptions<T>): Bytes {
|
||||
export function encode<T>(v: Encodable<T>, options?: EncoderOptions<T>): Bytes {
|
||||
return new Encoder(options).push(v).contents();
|
||||
}
|
||||
|
||||
let _nextId = 0;
|
||||
const _registry = new WeakMap<object, number>();
|
||||
export function pointerId(v: object): number {
|
||||
export function pointerId(v: any): number {
|
||||
let id = _registry.get(v);
|
||||
if (id === void 0) {
|
||||
id = _nextId++;
|
||||
|
@ -223,6 +223,6 @@ export function canonicalString(v: Encodable<any>): string {
|
|||
return _canonicalEncoder.push(v).contentsString();
|
||||
}
|
||||
|
||||
export function encodeWithAnnotations<T extends object>(v: Encodable<T>, options: EncoderOptions<T> = {}): Bytes {
|
||||
export function encodeWithAnnotations<T>(v: Encodable<T>, options: EncoderOptions<T> = {}): Bytes {
|
||||
return encode(v, { ... options, includeAnnotations: true });
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ export function floatValue(f: any): number {
|
|||
}
|
||||
|
||||
export class SingleFloat extends Float implements Preservable<never> {
|
||||
[AsPreserve]<T extends object = DefaultPointer>(): Value<T> {
|
||||
[AsPreserve]<T = DefaultPointer>(): Value<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ export function Single(value: number | Float): SingleFloat {
|
|||
}
|
||||
|
||||
export class DoubleFloat extends Float implements Preservable<never> {
|
||||
[AsPreserve]<T extends object = DefaultPointer>(): Value<T> {
|
||||
[AsPreserve]<T = DefaultPointer>(): Value<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,9 +5,9 @@ import { Set, Dictionary } from "./dictionary";
|
|||
import { annotate, Annotated } from "./annotated";
|
||||
import { Double, Float, Single } from "./float";
|
||||
|
||||
export type Fold<T extends object, R = Value<T>> = (v: Value<T>) => R;
|
||||
export type Fold<T, R = Value<T>> = (v: Value<T>) => R;
|
||||
|
||||
export interface FoldMethods<T extends object, R> {
|
||||
export interface FoldMethods<T, R> {
|
||||
boolean(b: boolean): R;
|
||||
single(f: number): R;
|
||||
double(f: number): R;
|
||||
|
@ -26,7 +26,7 @@ export interface FoldMethods<T extends object, R> {
|
|||
pointer(t: T, k: Fold<T, R>): R;
|
||||
}
|
||||
|
||||
export abstract class ValueFold<T extends object, R extends object = T> implements FoldMethods<T, Value<R>> {
|
||||
export abstract class ValueFold<T, R = T> implements FoldMethods<T, Value<R>> {
|
||||
boolean(b: boolean): Value<R> {
|
||||
return b;
|
||||
}
|
||||
|
@ -66,13 +66,13 @@ export abstract class ValueFold<T extends object, R extends object = T> implemen
|
|||
abstract pointer(t: T, k: Fold<T, Value<R>>): Value<R>;
|
||||
}
|
||||
|
||||
export class IdentityFold<T extends object> extends ValueFold<T, T> {
|
||||
export class IdentityFold<T> extends ValueFold<T, T> {
|
||||
pointer(t: T, _k: Fold<T, Value<T>>): Value<T> {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
export class MapFold<T extends object, R extends object> extends ValueFold<T, R> {
|
||||
export class MapFold<T, R extends object> extends ValueFold<T, R> {
|
||||
readonly f: (t: T) => Value<R>;
|
||||
|
||||
constructor(f: (t: T) => Value<R>) {
|
||||
|
@ -87,7 +87,7 @@ export class MapFold<T extends object, R extends object> extends ValueFold<T, R>
|
|||
|
||||
export const IDENTITY_FOLD = new IdentityFold();
|
||||
|
||||
export function fold<T extends object, R>(v: Value<T>, o: FoldMethods<T, R>): R {
|
||||
export function fold<T, R>(v: Value<T>, o: FoldMethods<T, R>): R {
|
||||
const walk = (v: Value<T>): R => {
|
||||
switch (typeof v) {
|
||||
case 'boolean':
|
||||
|
@ -130,7 +130,7 @@ export function fold<T extends object, R>(v: Value<T>, o: FoldMethods<T, R>): R
|
|||
return walk(v);
|
||||
}
|
||||
|
||||
export function mapPointers<T extends object, R extends object>(
|
||||
export function mapPointers<T, R extends object>(
|
||||
v: Value<T>,
|
||||
f: (t: T) => Value<R>,
|
||||
): Value<R>
|
||||
|
@ -138,7 +138,7 @@ export function mapPointers<T extends object, R extends object>(
|
|||
return fold(v, new MapFold(f));
|
||||
}
|
||||
|
||||
export function isPointer<T extends object>(v: Value<T>): v is T {
|
||||
export function isPointer<T>(v: Value<T>): v is T {
|
||||
return fold(v, {
|
||||
boolean(_b: boolean): boolean { return false; },
|
||||
single(_f: number): boolean { return false; },
|
||||
|
|
|
@ -3,7 +3,7 @@ import { Record, Tuple } from "./record";
|
|||
import { AsPreserve } from "./symbols";
|
||||
import { DefaultPointer, Value } from "./values";
|
||||
|
||||
export function fromJS<T extends object = DefaultPointer>(x: any): Value<T> {
|
||||
export function fromJS<T = DefaultPointer>(x: any): Value<T> {
|
||||
switch (typeof x) {
|
||||
case 'number':
|
||||
if (!Number.isInteger(x)) {
|
||||
|
|
|
@ -3,7 +3,7 @@ import type { Annotated } from "./annotated.js";
|
|||
|
||||
export const IsPreservesAnnotated = Symbol.for('IsPreservesAnnotated');
|
||||
|
||||
export function isAnnotated<T extends object = DefaultPointer>(x: any): x is Annotated<T>
|
||||
export function isAnnotated<T = DefaultPointer>(x: any): x is Annotated<T>
|
||||
{
|
||||
return !!x?.[IsPreservesAnnotated];
|
||||
}
|
||||
|
|
|
@ -9,8 +9,9 @@ import { decode } from './decoder';
|
|||
import { Record } from './record';
|
||||
import { annotate, Annotated } from './annotated';
|
||||
import { Double, DoubleFloat, Single, SingleFloat } from './float';
|
||||
import { stringify } from './text';
|
||||
|
||||
export interface ReaderOptions<T extends object> {
|
||||
export interface ReaderOptions<T> {
|
||||
includeAnnotations?: boolean;
|
||||
decodePointer?: (v: Value<T>) => T;
|
||||
}
|
||||
|
@ -19,7 +20,7 @@ type IntOrFloat = 'int' | 'float';
|
|||
type Numeric = number | SingleFloat | DoubleFloat;
|
||||
type IntContinuation = (kind: IntOrFloat, acc: string) => Numeric;
|
||||
|
||||
export class Reader<T extends object> {
|
||||
export class Reader<T> {
|
||||
buffer: string;
|
||||
index: number;
|
||||
discarded = 0;
|
||||
|
@ -214,7 +215,7 @@ export class Reader<T extends object> {
|
|||
switch (this.peek()) {
|
||||
case ':':
|
||||
if (acc.has(k)) this.error(
|
||||
`Duplicate key: ${k.asPreservesText()}`);
|
||||
`Duplicate key: ${stringify(k)}`);
|
||||
this.index++;
|
||||
acc.set(k, this.next());
|
||||
break;
|
||||
|
|
|
@ -3,7 +3,7 @@ import { DefaultPointer, Value } from "./values";
|
|||
|
||||
export type Tuple<T> = Array<T> | [T];
|
||||
|
||||
export type Record<LabelType extends Value<T>, FieldsType extends Tuple<Value<T>>, T extends object = DefaultPointer>
|
||||
export type Record<LabelType extends Value<T>, FieldsType extends Tuple<Value<T>>, T = DefaultPointer>
|
||||
= FieldsType & { label: LabelType };
|
||||
|
||||
export type RecordGetters<Fs, R> = {
|
||||
|
@ -13,27 +13,32 @@ export type RecordGetters<Fs, R> = {
|
|||
export type CtorTypes<Fs, Names extends Tuple<keyof Fs>> =
|
||||
{ [K in keyof Names]: Fs[keyof Fs & Names[K]] } & any[];
|
||||
|
||||
export interface RecordConstructor<L extends Value<T>, Fs, Names extends Tuple<keyof Fs>, T extends object = DefaultPointer> {
|
||||
export interface RecordConstructor<L extends Value<T>, Fs, Names extends Tuple<keyof Fs>, T = DefaultPointer> {
|
||||
(...fields: CtorTypes<Fs, Names>): Record<L, CtorTypes<Fs, Names>, T>;
|
||||
constructorInfo: RecordConstructorInfo<L, T>;
|
||||
isClassOf(v: any): v is Record<L, CtorTypes<Fs, Names>, T>;
|
||||
_: RecordGetters<Fs, Record<L, CtorTypes<Fs, Names>, T>>;
|
||||
};
|
||||
|
||||
export interface RecordConstructorInfo<L extends Value<T>, T extends object = DefaultPointer> {
|
||||
export interface RecordConstructorInfo<L extends Value<T>, T = DefaultPointer> {
|
||||
label: L;
|
||||
arity: number;
|
||||
}
|
||||
|
||||
export function Record<L extends Value<T>, FieldsType extends Tuple<Value<T>>, T extends object = DefaultPointer>(
|
||||
label: L, fields: FieldsType): Record<L, FieldsType, T>
|
||||
export function Record<L, FieldsType extends Tuple<any>>(
|
||||
label: L, fields: FieldsType):
|
||||
L extends Value<infer T>
|
||||
? (FieldsType extends Tuple<Value<T>>
|
||||
? Record<L, FieldsType, T>
|
||||
: never)
|
||||
: never
|
||||
{
|
||||
(fields as any).label = label;
|
||||
return fields as Record<L, FieldsType, T>;
|
||||
return fields as any;
|
||||
}
|
||||
|
||||
export namespace Record {
|
||||
export function isRecord<L extends Value<T>, FieldsType extends Tuple<Value<T>>, T extends object = DefaultPointer>(x: any): x is Record<L, FieldsType, T> {
|
||||
export function isRecord<L extends Value<T>, FieldsType extends Tuple<Value<T>>, T = DefaultPointer>(x: any): x is Record<L, FieldsType, T> {
|
||||
return Array.isArray(x) && 'label' in x;
|
||||
}
|
||||
|
||||
|
@ -41,29 +46,29 @@ export namespace Record {
|
|||
return '<unprintable_preserves_field_value>';
|
||||
}
|
||||
|
||||
export function constructorInfo<L extends Value<T>, FieldsType extends Tuple<Value<T>>, T extends object = DefaultPointer>(
|
||||
export function constructorInfo<L extends Value<T>, FieldsType extends Tuple<Value<T>>, T = DefaultPointer>(
|
||||
r: Record<L, FieldsType, T>): RecordConstructorInfo<L, T>
|
||||
{
|
||||
return { label: r.label, arity: r.length };
|
||||
}
|
||||
|
||||
export function isClassOf<L extends Value<T>, FieldsType extends Tuple<Value<T>>, T extends object = DefaultPointer>(
|
||||
export function isClassOf<L extends Value<T>, FieldsType extends Tuple<Value<T>>, T = DefaultPointer>(
|
||||
ci: RecordConstructorInfo<L, T>, v: any): v is Record<L, FieldsType, T>
|
||||
{
|
||||
return (Record.isRecord(v)) && is(ci.label, v.label) && (ci.arity === v.length);
|
||||
}
|
||||
|
||||
export function makeConstructor<Fs, T extends object = DefaultPointer>()
|
||||
export function makeConstructor<Fs, T = DefaultPointer>()
|
||||
: (<L extends Value<T>, Names extends Tuple<keyof Fs>>(label: L, fieldNames: Names) =>
|
||||
RecordConstructor<L, Fs, Names, T>)
|
||||
{
|
||||
return <L extends Value<T>, Names extends Tuple<keyof Fs>>(label: L, fieldNames: Names) => {
|
||||
const ctor: RecordConstructor<L, Fs, Names, T> =
|
||||
((...fields: CtorTypes<Fs, Names>) =>
|
||||
Record(label, fields)) as RecordConstructor<L, Fs, Names, T>;
|
||||
Record(label, fields)) as unknown as RecordConstructor<L, Fs, Names, T>;
|
||||
const constructorInfo = { label, arity: fieldNames.length };
|
||||
ctor.constructorInfo = constructorInfo;
|
||||
ctor.isClassOf = (v: any): v is Record<L, CtorTypes<Fs, Names>, T> => Record.isClassOf(constructorInfo, v);
|
||||
ctor.isClassOf = (v: any): v is Record<L, CtorTypes<Fs, Names>, T> => Record.isClassOf<L, CtorTypes<Fs, Names>, T>(constructorInfo, v);
|
||||
(ctor as any)._ = {};
|
||||
fieldNames.forEach((name, i) => (ctor._ as any)[name] = (r: Record<L, CtorTypes<Fs, Names>, T>) => r[i]);
|
||||
return ctor;
|
||||
|
|
|
@ -3,15 +3,15 @@ import { Annotated } from "./annotated";
|
|||
import { Record, Tuple } from "./record";
|
||||
import { Set, Dictionary } from "./dictionary";
|
||||
|
||||
export function unannotate<T extends object = DefaultPointer>(v: Value<T>): Value<T> {
|
||||
export function unannotate<T = DefaultPointer>(v: Value<T>): Value<T> {
|
||||
return Annotated.isAnnotated<T>(v) ? v.item : v;
|
||||
}
|
||||
|
||||
export function peel<T extends object = DefaultPointer>(v: Value<T>): Value<T> {
|
||||
export function peel<T = DefaultPointer>(v: Value<T>): Value<T> {
|
||||
return strip(v, 1);
|
||||
}
|
||||
|
||||
export function strip<T extends object = DefaultPointer>(
|
||||
export function strip<T = DefaultPointer>(
|
||||
v: Value<T>,
|
||||
depth: number = Infinity): Value<T>
|
||||
{
|
||||
|
|
|
@ -5,9 +5,9 @@ import type { DoubleFloat, SingleFloat } from './float';
|
|||
import type { Annotated } from './annotated';
|
||||
import type { Set, Dictionary } from './dictionary';
|
||||
|
||||
export type DefaultPointer = object;
|
||||
export type DefaultPointer = never;
|
||||
|
||||
export type Value<T extends object = DefaultPointer> =
|
||||
export type Value<T = DefaultPointer> =
|
||||
| Atom
|
||||
| Compound<T>
|
||||
| T
|
||||
|
@ -20,7 +20,7 @@ export type Atom =
|
|||
| string
|
||||
| Bytes
|
||||
| symbol;
|
||||
export type Compound<T extends object = DefaultPointer> =
|
||||
export type Compound<T = DefaultPointer> =
|
||||
| (Array<Value<T>> | [Value<T>]) & { label: Value<T> }
|
||||
// ^ expanded from definition of Record<> in record.ts,
|
||||
// because if we use Record<Value<T>, Tuple<Value<T>>, T>,
|
||||
|
|
Loading…
Reference in New Issue