import type { Resolve } from "@rickosborne/typical"; /** * Partial property descriptor which has been * marked as non-writable. */ export type ReadOnlyPropertyDescriptor = { writable: false; }; /** * Basic flags for any property descriptor. */ export type PropertyDescriptorFlags = { configurable?: boolean; enumerable?: boolean; writable?: boolean; }; /** * Partial property descriptor which contains a static value, * instead of an accessor and/or mutator. */ export type ValuePropertyDescriptor = PropertyDescriptorFlags & { get?: never; set?: never; value: T; }; /** * Partial property descriptor which includes only an accessor (getter) * and not a mutator, and is thus read-only. */ export type GetPropertyDescriptor = PropertyDescriptorFlags & { get(): T; set?: never; value?: never; }; /** * Partial property descriptor which includes only a mutator (setter) * and not an accessor (getter), and is thus write-only. * Note: TypeScript support for these kinds of properties is very * poor as of v5.7. */ export type SetPropertyDescriptor = PropertyDescriptorFlags & { get?: never; set(t: T): void; }; /** * Partial property descriptor which includes both an accessor (getter) * and mutator (setter), and is thus read-write. */ export type GetSetPropertyDescriptor = PropertyDescriptorFlags & { get(): T; set(t: T): void; }; /** * Union for reasonable configurations of property descriptors which * could affect the type for the property. */ export type TypedPropertyDescriptor = ValuePropertyDescriptor | GetPropertyDescriptor | SetPropertyDescriptor | GetSetPropertyDescriptor; /** * Filter type T based on whether the property descriptor * D would produce a read-only property. */ export type IfReadOnlyDescriptor> = D extends ReadOnlyPropertyDescriptor | GetPropertyDescriptor ? T : never; /** * Filter type T based on whether the property descriptor * D would produce a read-write (or write-only) property. */ export type IfReadWriteDescriptor> = D extends ReadOnlyPropertyDescriptor | GetPropertyDescriptor | SetPropertyDescriptor ? never : T; /** * Mangle the given Key to $\{Key\}IsWriteOnly if * property descriptor D would produce a write-only property. */ export type RenameIfWriteOnlyDescriptor> = D extends SetPropertyDescriptor ? `${Key}IsWriteOnly` : never; /** * Filter type T based on whether the property descriptor * D would produce a write-only property. * Note: * JS has a concept of a write-only property, and the unit tests cover this. * However, TS doesn't have a way of expressing it, at least as of v5.8. * So for now, it goes into the read-write bucket, even though you can't * actually read from it. * The alternative would be to set it to `undefined`, to show you can't * read from it ... but then you lose the type info for the setter. Yuck. * For now ... * The types below will, ahem, mangle the types they produce. Just a little. * If you produce a setter-only property, it will end up looking like: * ```typescript * const withSetterOnly: WithSetterOnly = addProperty({}, "whatever", { set: (value: string) => void(whatever(value)) }); * type WithSetterOnly = { * whatever: string; * whateverIsWriteOnly?: undefined; * } * ``` * So you get a reminder without breaking anything too hard. */ export type IfWriteOnlyDescriptor> = D extends SetPropertyDescriptor ? T : never; /** * Produce the keys for the given property descriptors record which * would produce read-only properties. */ export type ReadOnlyDescriptorsKeys = R extends Record> ? { [key in K]: IfReadOnlyDescriptor; }[K] : never; /** * Produce the keys for the given property descriptors record which * would produce read-write (or write-only) properties. */ export type ReadWriteDescriptorsKeys = R extends Record> ? { [key in K]: IfReadWriteDescriptor; }[K] : never; /** * Produce the non-mangled keys for the given property * descriptors record which would produce write-only properties. */ export type WriteOnlyDescriptorsKeys = R extends Record> ? { [key in string & K]: IfWriteOnlyDescriptor; }[string & K] : never; /** * Produce the mangled keys for the given property * descriptors record which would produce write-only properties. * See {@link RenameIfWriteOnlyDescriptor} for details on the mangling. */ export type RenamedWriteOnlyDescriptorsKeys = R extends Record> ? { [key in string & K]: RenameIfWriteOnlyDescriptor; }[string & K] : never; /** * Produce a single-property object type for the given property * descriptor. Note: will produce an additional mangled pseudo-property * for write-only properties. * See {@link RenameIfWriteOnlyDescriptor} for details on the mangling. */ export type PropertyFromDescriptor> = D extends TypedPropertyDescriptor ? ({ readonly [key in IfReadOnlyDescriptor]: V; } & { [key in IfReadWriteDescriptor]: V; } & { [key in IfWriteOnlyDescriptor]: V; } & { [key in RenameIfWriteOnlyDescriptor]?: undefined; }) : never; /** * Produce an object with the properties described by the descriptors. * See {@link RenameIfWriteOnlyDescriptor} for details on the mangling * of write-only properties. */ export type PropertiesFromDescriptors>> = { readonly [K in ReadOnlyDescriptorsKeys]: R[K] extends TypedPropertyDescriptor ? V : never; } & { [K in ReadWriteDescriptorsKeys]: R[K] extends TypedPropertyDescriptor ? V : never; } & { [K in WriteOnlyDescriptorsKeys]: R[K] extends TypedPropertyDescriptor ? V : never; } & { [K in RenamedWriteOnlyDescriptorsKeys]?: undefined; }; /** * A more type-friendly version of Object.defineProperty. * See {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty | Object.defineProperty on MDN}. */ export declare const addProperty: >(target: T, key: K, descriptor: D) => Resolve>; /** * A more type-friendly version of Object.defineProperties. * See {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties | Object.defineProperties on MDN}. */ export declare const addProperties: >>(target: T, descriptors: R) => Resolve>; //# sourceMappingURL=add-property.d.ts.map