stampit 4.3 - better typing through generics (#39188)

* stampit 4.3

* fix `Error: stampit: Older version 3 must have a path mapping for itself.`

* fix`baseUrl` & `typeRoots`

* Some dtslint compliance

* header fix

* enhance

* tests

* tslint:disable

* naming

* fix refs/props changes + ExtendedDescriptor

* more $ExpectType tests

* Tentative `MethodMap` fix

* Updated  `MethodMap`tests

* additional testing (failing)

* fix `Composable` signature
This commit is contained in:
PopGoesTheWza 2019-10-30 15:35:36 +01:00 committed by Jesse Trinity
parent 5bf2bc31a5
commit d77ee72756
8 changed files with 1387 additions and 450 deletions

View File

@ -1,518 +1,566 @@
// Type definitions for stampit 3.0
// Type definitions for stampit 4.3
// Project: https://github.com/stampit-org/stampit, https://stampit.js.org
// Definitions by: Vasyl Boroviak <https://github.com/koresar>
// Harris Lummis <https://github.com/lummish>
// PopGoesTheWza <https://github.com/popgoesthewza>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 3.5
// Utility types
/**
* Function used as .init() argument.
* @internal Base type for all `methods`-like metadata.
* @template This The type to use for `this` within methods.
*/
type Init = (factoryArg: any, ctx?: Context) => any;
/**
* Composer function
*/
type Composer = ({ stamp, composables }: { stamp: stampit.Stamp; composables: Composable[] }) => any;
/** The stamp Descriptor */
interface Descriptor {
/** Create a new stamp based on this descriptor */
(...composables: Composable[]): stampit.Stamp;
/**
* A hash containing methods (functions) of any future created instance.
*/
methods?: {};
/**
* Initialization function(s) which will be called per each newly created
* instance.
*/
initializers?: Init[];
/**
* Properties which will shallowly copied into any future created instance.
*/
properties?: {};
/**
* Properties which will be mixed to the new and any other stamp which this stamp will be composed with.
*/
staticProperties?: {};
/** Deeply merged properties of object instances */
deepProperties?: {};
/** ES5 Property Descriptors applied to object instances */
propertyDescriptors?: {};
/** Deeply merged properties of Stamps */
staticDeepProperties?: {};
/** ES5 Property Descriptors applied to Stamps */
staticPropertyDescriptors?: {};
/** A configuration object to be shallowly assigned to Stamps */
configuration?: {};
/** A configuration object to be deeply merged to Stamps */
deepConfiguration?: {};
interface MethodMap<This> {
[s: string]: ((this: This, ...args: any[]) => any) | {};
}
/** Any composable object (stamp or descriptor) */
type Composable = stampit.Stamp | Descriptor;
/** @internal A plain old JavaScript object created by a `Stamp`. */
type Pojo = object; // { [s: string]: any; }
/**
* The .init() function argument.
*/
interface Context {
/**
* The object which has been just instantiated.
*/
instance: any;
/** @internal Base type for all `properties`-like metadata. */
// TODO: discriminate Array
type PropertyMap = object; // { [s: string]: any; }
/**
* The stamp the object has been instantiated with.
*/
stamp: stampit.Stamp;
/**
* The arguments list passed to the stamp.
*/
args: any[];
/** @internal Signature common to every `Stamp`s. */
interface StampSignature {
(options?: PropertyMap, ...args: unknown[]): any;
compose: ComposeMethod & stampit.Descriptor<any, any>;
}
interface Options {
/**
* A hash containing methods (functions) of any future created instance.
*/
methods?: {};
/**
* Initialization function(s) which will be called per each newly created
* instance.
*/
init?: Init | Init[];
/**
* Initialization function(s) which will be called per each newly created
* instance.
*/
initializers?: Init | Init[];
/**
* Properties which will shallowly copied into any future created instance.
*/
props?: {};
/**
* Properties which will shallowly copied into any future created instance.
*/
properties?: {};
/**
* A hash containing references to the object. This hash will be shallow mixed into any future created instance.
*/
refs?: {};
/**
* Properties which will be mixed to the new and any other stamp which this
* stamp will be composed with.
*/
staticProperties?: {};
/**
* Properties which will be mixed to the new and any other stamp which this
* stamp will be composed with.
*/
statics?: {};
/** Deeply merged properties of object instances */
deepProperties?: {};
/** Deeply merged properties of object instances */
deepProps?: {};
/** ES5 Property Descriptors applied to object instances */
propertyDescriptors?: {};
/** Deeply merged properties of Stamps */
staticDeepProperties?: {};
/** Deeply merged properties of Stamps */
deepStatics?: {};
/** ES5 Property Descriptors applied to Stamps */
staticPropertyDescriptors?: {};
/** A configuration object to be shallowly assigned to Stamps */
configuration?: {};
/** A configuration object to be shallowly assigned to Stamps */
conf?: {};
/** A configuration object to be deeply merged to Stamps */
deepConfiguration?: {};
/** A configuration object to be deeply merged to Stamps */
deepConf?: {};
/** Callback functions to execute each time a composition occurs */
composers?: Composer[];
}
/** Stampit Composable for main stampit() function */
type StampitComposable = stampit.Stamp | Descriptor | Options;
/**
* @internal Extracts the `Stamp` type.
* @template Original The type to extract the `Stamp` type from.
*/
type StampType<Original> = Original extends /* disallowed types */ [] | bigint
? never
: stampit.IsADescriptor<Original> extends true
? (Original extends stampit.ExtendedDescriptor<infer Obj, infer Stamp> ? Stamp : never)
: unknown extends Original /* is any or unknown */
? stampit.Stamp<Original>
: Original extends StampSignature
? Original
: Original extends stampit.ExtendedDescriptor<infer Obj, any>
? stampit.Stamp<Obj>
: Original extends Pojo
? stampit.Stamp<Original> /*assume it is the object from a stamp object*/
: never;
/**
* Return a factory (aka Stamp) function that will produce new objects using the
* prototypes that are passed in or composed.
* @param options Stampit options object containing refs, methods,
* init, props, statics, configurations, and property descriptors.
* @internal The type of the object produced by the `Stamp`.
* @template Original The type (either a `Stamp` or a `ExtendedDescriptor`) to get the object type from.
*/
declare function stampit(...composables: StampitComposable[]): stampit.Stamp;
type StampObjectType<Original> = Original extends /* disallowed types */ bigint | boolean | number | string | symbol
? never
: stampit.IsADescriptor<Original> extends true
? (Original extends stampit.ExtendedDescriptor<infer Obj, any> ? Obj : never)
: unknown extends Original /* is any or unknown */
? Original
: Original extends StampSignature
? (Original extends stampit.Stamp<infer Obj> /* extended stamps may require infering twice */
? (Obj extends stampit.Stamp<infer Obj> ? Obj : Obj)
: any)
: Original extends stampit.ExtendedDescriptor<infer Obj, any>
? Obj
: Original extends Pojo
? Original
: never;
/**
* A factory function to create plain object instances.
* @template Obj The object type that the `Stamp` will create.
*/
interface FactoryFunction<Obj> {
(options?: PropertyMap, ...args: any[]): StampObjectType<Obj>;
}
/**
* @internal Chainables `Stamp` additionnal methods
* @template Obj The object type that the `Stamp` will create.
*/
type StampChainables<Obj> = Chainables<StampObjectType<Obj>, StampType<Obj>>;
/**
* @internal Chainables `Stamp` additionnal methods
* @template Obj The object type that the `Stamp` will create.
* @template S̤t̤a̤m̤p̤ The type of the `Stamp` (when extending a `Stamp`.)
*/
interface Chainables<Obj, S̤t̤a̤m̤p̤ extends StampSignature> {
/**
* Add methods to the methods prototype. Creates and returns new Stamp. **Chainable**.
* @template This The type to use for `this` within methods.
* @param methods Object(s) containing map of method names and bodies for delegation.
*/
// tslint:disable-next-line: no-unnecessary-generics
methods<This = Obj>(...methods: Array<MethodMap<This>>): S̤t̤a̤m̤p̤;
/**
* Take a variable number of objects and shallow assign them to any future created instance of the Stamp. Creates and returns new Stamp. **Chainable**.
* @param objects Object(s) to shallow assign for each new object.
*/
properties(...objects: PropertyMap[]): S̤t̤a̤m̤p̤;
/**
* Take a variable number of objects and shallow assign them to any future created instance of the Stamp. Creates and returns new Stamp. **Chainable**.
* @param objects Object(s) to shallow assign for each new object.
*/
props(...objects: PropertyMap[]): S̤t̤a̤m̤p̤;
/**
* Take a variable number of objects and deeply merge them to any future created instance of the Stamp. Creates and returns a new Stamp. **Chainable**.
* @param deepObjects The object(s) to deeply merge for each new object.
*/
deepProperties(...deepObjects: PropertyMap[]): S̤t̤a̤m̤p̤;
/**
* Take a variable number of objects and deeply merge them to any future created instance of the Stamp. Creates and returns a new Stamp. **Chainable**.
* @param deepObjects The object(s) to deeply merge for each new object.
*/
deepProps(...deepObjects: PropertyMap[]): S̤t̤a̤m̤p̤;
/**
* Take in a variable number of functions and add them to the initializers prototype as initializers. **Chainable**.
* @param functions Initializer functions used to create private data and privileged methods.
*/
initializers(...functions: Array<stampit.Initializer<Obj, S̤t̤a̤m̤p̤>>): S̤t̤a̤m̤p̤;
initializers(functions: Array<stampit.Initializer<Obj, S̤t̤a̤m̤p̤>>): S̤t̤a̤m̤p̤;
/**
* Take in a variable number of functions and add them to the initializers prototype as initializers. **Chainable**.
* @param functions Initializer functions used to create private data and privileged methods.
*/
init(...functions: Array<stampit.Initializer<Obj, S̤t̤a̤m̤p̤>>): S̤t̤a̤m̤p̤;
init(functions: Array<stampit.Initializer<Obj, S̤t̤a̤m̤p̤>>): S̤t̤a̤m̤p̤;
/**
* Take n objects and add them to a new stamp and any future stamp it composes with. Creates and returns new Stamp. **Chainable**.
* @param statics Object(s) containing map of property names and values to mixin into each new stamp.
*/
staticProperties(...statics: PropertyMap[]): S̤t̤a̤m̤p̤;
/**
* Take n objects and add them to a new stamp and any future stamp it composes with. Creates and returns new Stamp. **Chainable**.
* @param statics Object(s) containing map of property names and values to mixin into each new stamp.
*/
statics(...statics: PropertyMap[]): S̤t̤a̤m̤p̤;
/**
* Deeply merge a variable number of objects and add them to a new stamp and any future stamp it composes. Creates and returns a new Stamp. **Chainable**.
* @param deepStatics The object(s) containing static properties to be merged.
*/
staticDeepProperties(...deepStatics: PropertyMap[]): S̤t̤a̤m̤p̤;
/**
* Deeply merge a variable number of objects and add them to a new stamp and any future stamp it composes. Creates and returns a new Stamp. **Chainable**.
* @param deepStatics The object(s) containing static properties to be merged.
*/
deepStatics(...deepStatics: PropertyMap[]): S̤t̤a̤m̤p̤;
/**
* Take in a variable number of functions and add them to the composers prototype as composers. **Chainable**.
* @param functions Composer functions that will run in sequence while creating a new stamp from a list of composables. The resulting stamp and the composables get passed to composers.
*/
composers(...functions: Array<stampit.Composer<S̤t̤a̤m̤p̤>>): S̤t̤a̤m̤p̤;
composers(functions: Array<stampit.Composer<S̤t̤a̤m̤p̤>>): S̤t̤a̤m̤p̤;
/**
* Shallowly assign properties of Stamp arbitrary metadata and add them to a new stamp and any future Stamp it composes. Creates and returns a new Stamp. **Chainable**.
* @param confs The object(s) containing metadata properties.
*/
configuration(...confs: PropertyMap[]): S̤t̤a̤m̤p̤;
/**
* Shallowly assign properties of Stamp arbitrary metadata and add them to a new stamp and any future Stamp it composes. Creates and returns a new Stamp. **Chainable**.
* @param confs The object(s) containing metadata properties.
*/
conf(...confs: PropertyMap[]): S̤t̤a̤m̤p̤;
/**
* Deeply merge properties of Stamp arbitrary metadata and add them to a new Stamp and any future Stamp it composes. Creates and returns a new Stamp. **Chainable**.
* @param deepConfs The object(s) containing metadata properties.
*/
deepConfiguration(...deepConfs: PropertyMap[]): S̤t̤a̤m̤p̤;
/**
* Deeply merge properties of Stamp arbitrary metadata and add them to a new Stamp and any future Stamp it composes. Creates and returns a new Stamp. **Chainable**.
* @param deepConfs The object(s) containing metadata properties.
*/
deepConf(...deepConfs: PropertyMap[]): S̤t̤a̤m̤p̤;
/**
* Apply ES5 property descriptors to object instances created by the new Stamp returned by the function and any future Stamp it composes. Creates and returns a new stamp. **Chainable**.
* @param descriptors
*/
propertyDescriptors(...descriptors: PropertyDescriptorMap[]): S̤t̤a̤m̤p̤;
/**
* Apply ES5 property descriptors to a Stamp and any future Stamp it composes. Creates and returns a new stamp. **Chainable**.
* @param descriptors
*/
staticPropertyDescriptors(...descriptors: PropertyDescriptorMap[]): S̤t̤a̤m̤p̤;
}
/**
* A function which creates a new `Stamp`s from a list of `Composable`s.
* @template Obj The type of the object instance being produced by the `Stamp` or the type of the `Stamp` being created (when extending a `Stamp`.)
*/
type ComposeMethod = typeof stampit;
/**
* A function which creates a new `Stamp`s from a list of `Composable`s.
* @template Obj The type of the object instance being created by the `Stamp` or the type of the `Stamp` being created (when extending a `Stamp`.)
*/
// tslint:disable-next-line: no-unnecessary-generics
declare function stampit<Obj = any>(...composables: stampit.Composable[]): StampType<Obj>;
declare namespace stampit {
/** A composable object (either a `Stamp` or a `ExtendedDescriptor`.) */
type Composable = StampSignature | ExtendedDescriptor<any, any>;
/**
* A factory function that will produce new objects using the
* prototypes that are passed in or composed.
* A `Stamp`'s metadata.
* @template Obj The type of the object instance being produced by the `Stamp`.
* @template S̤t̤a̤m̤p̤ The type of the `Stamp` (when extending a `Stamp`.)
*/
interface Stamp {
/**
* Invokes the stamp and returns a new object instance.
* @param state Properties you wish to set on the new objects.
* @param encloseArgs The remaining arguments are passed to all .enclose() functions.
* WARNING Avoid using two different .enclose() functions that expect different arguments.
* .enclose() functions that take arguments should not be considered safe to compose
* with other .enclose() functions that also take arguments. Taking arguments with
* an .enclose() function is an anti-pattern that should be avoided, when possible.
* @return A new object composed of the Stamps and prototypes provided.
*/
(state?: {}, ...encloseArgs: any[]): any;
/**
* Just like calling stamp(), stamp.create() invokes the stamp and returns a new instance.
* @param state Properties you wish to set on the new objects.
* @param encloseArgs The remaining arguments are passed to all .enclose() functions.
* WARNING Avoid using two different .enclose() functions that expect different arguments.
* .enclose() functions that take arguments should not be considered safe to compose
* with other .enclose() functions that also take arguments. Taking arguments with
* an .enclose() function is an anti-pattern that should be avoided, when possible.
* @return A new object composed of the Stamps and prototypes provided.
*/
create(state?: {}, ...encloseArgs: any[]): any;
/**
* Stamp metadata/composer function
*/
compose: Descriptor;
/**
* Add methods to the methods prototype. Creates and returns new Stamp. Chainable.
* @param methods Object(s) containing map of method names and bodies for delegation.
* @return A new Stamp.
*/
methods(...methods: Array<{}>): Stamp;
/**
* Take n objects and add them to the state prototype. Creates and returns new Stamp. Chainable.
* @param states Object(s) containing map of property names and values to clone for each new object.
* @return A new Stamp.
*/
refs(...states: Array<{}>): Stamp;
/**
* Take a variable number of objects and shallow assign them to any future
* created instance of the Stamp. Creates and returns new Stamp. Chainable.
* @param objects Object(s) to shallow assign for each new object.
* @return A new Stamp.
*/
props(...objects: Array<{}>): Stamp;
/**
* Take a variable number of objects and shallow assign them to any future
* created instance of the Stamp. Creates and returns new Stamp. Chainable.
* @param objects Object(s) to shallow assign for each new object.
* @return A new Stamp.
*/
properties(...objects: Array<{}>): Stamp;
/**
* Take a variable number of objects and deeply merge them to any future
* created instance of the Stamp. Creates and returns a new Stamp.
* Chainable.
* @param deepObjects The object(s) to deeply merge for each new object
* @returns A new Stamp
*/
deepProps(...deepObjects: Array<{}>): Stamp;
/**
* Take a variable number of objects and deeply merge them to any future
* created instance of the Stamp. Creates and returns a new Stamp.
* Chainable.
* @param deepObjects The object(s) to deeply merge for each new object
* @returns A new Stamp
*/
deepProperties(...deepObjects: Array<{}>): Stamp;
/**
* @deprecated Use .init() instead.
*/
enclose(...functions: Init[]): Stamp;
/**
* @deprecated Use .init() instead.
*/
enclose(...functions: Array<{}>): Stamp;
/**
* Take in a variable number of functions and add them to the enclose
* prototype as initializers.
* @param functions Initializer functions used to create private data and
* privileged methods
* @returns A new stamp
*/
init(...functions: Init[]): Stamp;
/**
* Take in a variable number of functions and add them to the enclose
* prototype as initializers.
* @param functions Initializer functions used to create private data and
* privileged methods
* @returns A new stamp
*/
init(functions: Init[]): Stamp;
/**
* Take in a variable number of functions and add them to the enclose
* prototype as initializers.
* @param functions Initializer functions used to create private data and
* privileged methods
* @returns A new stamp
*/
initializers(...functions: Init[]): Stamp;
/**
* Take in a variable number of functions and add them to the enclose
* prototype as initializers.
* @param functions Initializer functions used to create private data and
* privileged methods
* @returns A new stamp
*/
initializers(functions: Init[]): Stamp;
/**
* Take n objects and add them to a new stamp and any future stamp it composes with.
* Creates and returns new Stamp. Chainable.
* @param statics Object(s) containing map of property names and values to mixin into each new stamp.
* @return A new Stamp.
*/
statics(...statics: Array<{}>): Stamp;
/**
* Take n objects and add them to a new stamp and any future stamp it composes with.
* Creates and returns new Stamp. Chainable.
* @param statics Object(s) containing map of property names and values to mixin into each new stamp.
* @return A new Stamp.
*/
staticProperties(...statics: Array<{}>): Stamp;
/**
* Deeply merge a variable number of objects and add them to a new stamp and
* any future stamp it composes. Creates and returns a new Stamp. Chainable.
* @param deepStatics The object(s) containing static properties to be
* merged
* @returns A new stamp
*/
deepStatics(...deepStatics: Array<{}>): Stamp;
/**
* Deeply merge a variable number of objects and add them to a new stamp and
* any future stamp it composes. Creates and returns a new Stamp. Chainable.
* @param deepStatics The object(s) containing static properties to be
* merged
* @returns A new stamp
*/
staticDeepProperties(...deepStatics: Array<{}>): Stamp;
/**
* Shallowly assign properties of Stamp arbitrary metadata and add them to
* a new stamp and any future Stamp it composes. Creates and returns a new
* Stamp. Chainable.
* @param confs The object(s) containing metadata properties
* @returns A new Stamp
*/
conf(...confs: Array<{}>): Stamp;
/**
* Shallowly assign properties of Stamp arbitrary metadata and add them to
* a new stamp and any future Stamp it composes. Creates and returns a new
* Stamp. Chainable.
* @param confs The object(s) containing metadata properties
* @returns A new Stamp
*/
configuration(...confs: Array<{}>): Stamp;
/**
* Deeply merge properties of Stamp arbitrary metadata and add them to a new
* Stamp and any future Stamp it composes. Creates and returns a new Stamp.
* Chainable.
* @param deepConfs The object(s) containing metadata properties
* @returns A new Stamp
*/
deepConf(...deepConfs: Array<{}>): Stamp;
/**
* Deeply merge properties of Stamp arbitrary metadata and add them to a new
* Stamp and any future Stamp it composes. Creates and returns a new Stamp.
* Chainable.
* @param deepConfs The object(s) containing metadata properties
* @returns A new Stamp
*/
deepConfiguration(...deepConfs: Array<{}>): Stamp;
/**
* Apply ES5 property descriptors to object instances created by the new
* Stamp returned by the function and any future Stamp it composes. Creates
* and returns a new stamp. Chainable.
* @param descriptors
* @returns A new Stamp
*/
propertyDescriptors(...descriptors: Array<{}>): Stamp;
/**
* Apply ES5 property descriptors to a Stamp and any future Stamp it
* composes. Creates and returns a new stamp. Chainable.
* @param descriptors
* @returns A new Stamp
*/
staticPropertyDescriptors(...descriptors: Array<{}>): Stamp;
interface Descriptor<Obj, S̤t̤a̤m̤p̤ extends StampSignature = Stamp<Obj>> {
/** A set of methods that will be added to the object's delegate prototype. */
methods?: MethodMap<Obj>;
/** A set of properties that will be added to new object instances by assignment. */
properties?: PropertyMap;
/** A set of properties that will be added to new object instances by deep property merge. */
deepProperties?: PropertyMap;
/** A set of object property descriptors (`PropertyDescriptor`) used for fine-grained control over object property behaviors. */
propertyDescriptors?: PropertyDescriptorMap;
/** A set of static properties that will be copied by assignment to the `Stamp`. */
staticProperties?: PropertyMap /* & ThisType<S> */;
/** A set of static properties that will be added to the `Stamp` by deep property merge. */
staticDeepProperties?: PropertyMap /* & ThisType<S> */;
/** A set of object property descriptors (`PropertyDescriptor`) to apply to the `Stamp`. */
staticPropertyDescriptors?: PropertyDescriptorMap /* & ThisType<S> */;
/** An array of functions that will run in sequence while creating an object instance from a `Stamp`. `Stamp` details and arguments get passed to initializers. */
initializers?: Initializer<Obj, S̤t̤a̤m̤p̤> | Array<Initializer<Obj, S̤t̤a̤m̤p̤>>;
/** An array of functions that will run in sequence while creating a new `Stamp` from a list of `Composable`s. The resulting `Stamp` and the `Composable`s get passed to composers. */
composers?: Array<Composer<S̤t̤a̤m̤p̤>>;
/** A set of options made available to the `Stamp` and its initializers during object instance creation. These will be copied by assignment. */
configuration?: PropertyMap /* & ThisType<S> */;
/** A set of options made available to the `Stamp` and its initializers during object instance creation. These will be deep merged. */
deepConfiguration?: PropertyMap /* & ThisType<S> */;
}
/**
* A shortcut methods for stampit().methods()
* A `stampit`'s metadata.
* @template Obj The type of the object instance being produced by the `Stamp`.
* @template S̤t̤a̤m̤p̤ The type of the `Stamp` (when extending a `Stamp`.)
*/
interface ExtendedDescriptor<Obj, S̤t̤a̤m̤p̤ extends StampSignature = Stamp<Obj>> extends Descriptor<Obj, S̤t̤a̤m̤p̤> {
/** A set of properties that will be added to new object instances by assignment. */
props?: PropertyMap;
/** A set of properties that will be added to new object instances by deep property merge. */
deepProps?: PropertyMap;
/** A set of static properties that will be copied by assignment to the `Stamp`. */
statics?: PropertyMap /* & ThisType<S> */;
/** A set of static properties that will be added to the `Stamp` by deep property merge. */
deepStatics?: PropertyMap /* & ThisType<S> */;
/** An array of functions that will run in sequence while creating an object instance from a `Stamp`. `Stamp` details and arguments get passed to initializers. */
init?: Initializer<Obj, S̤t̤a̤m̤p̤> | Array<Initializer<Obj, S̤t̤a̤m̤p̤>>;
/** A set of options made available to the `Stamp` and its initializers during object instance creation. These will be copied by assignment. */
conf?: PropertyMap /* & ThisType<S> */;
/** A set of options made available to the `Stamp` and its initializers during object instance creation. These will be deep merged. */
deepConf?: PropertyMap /* & ThisType<S> */;
// TODO: Add description
name?: string;
}
/**
* @internal Checks that a type is a ExtendedDescriptor (except `any` and `unknown`).
* @template Type A type to check if a ExtendedDescriptor.
*/
// TODO: Improve test by checking the type of common keys
type IsADescriptor<Type> = unknown extends Type
? (keyof Type extends never
? false
: keyof Type extends infer K
? (K extends keyof ExtendedDescriptor<unknown> ? true : false)
: false)
: false;
/**
* A function used as `.initializers` argument.
* @template Obj The type of the object instance being produced by the `Stamp`.
* @template S̤t̤a̤m̤p̤ The type of the `Stamp` producing the instance.
*/
interface Initializer<Obj, S̤t̤a̤m̤p̤ extends StampSignature> {
(this: Obj, options: /*_propertyMap*/ any, context: InitializerContext<Obj, S̤t̤a̤m̤p̤>): void | Obj;
}
/**
* The `Initializer` function context.
* @template Obj The type of the object instance being produced by the `Stamp`.
* @template S̤t̤a̤m̤p̤ The type of the `Stamp` producing the instance.
*/
interface InitializerContext<Obj, S̤t̤a̤m̤p̤ extends StampSignature> {
/** The object instance being produced by the `Stamp`. If the initializer returns a value other than `undefined`, it replaces the instance. */
instance: Obj;
/** A reference to the `Stamp` producing the instance. */
stamp: S̤t̤a̤m̤p̤;
/** An array of the arguments passed into the `Stamp`, including the options argument. */
// ! above description from the specification is obscure
args: any[];
}
/**
* A function used as `.composers` argument.
* @template S̤t̤a̤m̤p̤ The type of the `Stamp` produced by the `.compose()` method.
*/
interface Composer<S̤t̤a̤m̤p̤ extends StampSignature> {
(parameters: ComposerParameters<S̤t̤a̤m̤p̤>): void | S̤t̤a̤m̤p̤;
}
/**
* The parameters received by the current `.composers` function.
* @template S̤t̤a̤m̤p̤ The type of the `Stamp` produced by the `.compose()` method.
*/
interface ComposerParameters<S̤t̤a̤m̤p̤ extends StampSignature> {
/** The result of the `Composable`s composition. */
stamp: S̤t̤a̤m̤p̤;
/** The list of composables the `Stamp` was just composed of. */
composables: Composable[];
}
/**
* A factory function to create plain object instances.
*
* It also has a `.compose()` method which is a copy of the `ComposeMethod` function and a `.compose` accessor to its `Descriptor`.
* @template Obj The object type that the `Stamp` will create.
*/
interface Stamp<Obj> extends FactoryFunction<Obj>, StampChainables<Obj>, StampSignature {
/** Just like calling stamp(), stamp.create() invokes the stamp and returns a new instance. */
create: FactoryFunction<Obj>;
/**
* A function which creates a new `Stamp`s from a list of `Composable`s.
* @template Obj The type of the object instance being produced by the `Stamp`. or the type of the `Stamp` being created.
*/
compose: ComposeMethod & Descriptor<StampObjectType<Obj>>;
}
/**
* A shortcut method for stampit().methods()
*
* Add methods to the methods prototype. Creates and returns new Stamp. **Chainable**.
* @template Obj The type of the object instance being produced by the `Stamp`. or the type of the `Stamp` being created.
* @template This The type to use for `this` within methods.
* @param methods Object(s) containing map of method names and bodies for delegation.
* @return A new Stamp.
*/
function methods(...methods: Array<{}>): Stamp;
/**
* A shortcut methods for stampit().refs()
* @param states Object(s) containing map of property names and values to clone for each new object.
* @return A new Stamp.
*/
function refs(...states: Array<{}>): Stamp;
/**
* A shortcut method for stampit().props()
* @param objects Object(s) to shallow assign for each new object.
* @return A new Stamp.
*/
function props(...objects: Array<{}>): Stamp;
function methods<Obj = any>(this: StampObjectType<Obj>, ...methods: Array<MethodMap<Obj>>): StampType<Obj>;
/**
* A shortcut method for stampit().properties()
*
* Take a variable number of objects and shallow assign them to any future created instance of the Stamp. Creates and returns new Stamp. **Chainable**.
* @template Obj The type of the object instance being produced by the `Stamp`. or the type of the `Stamp` being created.
* @param objects Object(s) to shallow assign for each new object.
* @return A new Stamp.
*/
function properties(...objects: Array<{}>): Stamp;
// tslint:disable-next-line: no-unnecessary-generics
function properties<Obj = any>(...objects: PropertyMap[]): StampType<Obj>;
/**
* A shortcut method for stampit().deepProps()
* @param deepObjects The object(s) to deeply merge for each new object
* @returns A new Stamp
* A shortcut method for stampit().props()
*
* Take a variable number of objects and shallow assign them to any future created instance of the Stamp. Creates and returns new Stamp. **Chainable**.
* @template Obj The type of the object instance being produced by the `Stamp`. or the type of the `Stamp` being created.
* @param objects Object(s) to shallow assign for each new object.
*/
function deepProps(...deepObjects: Array<{}>): Stamp;
// tslint:disable-next-line: no-unnecessary-generics
function props<Obj = any>(...objects: PropertyMap[]): StampType<Obj>;
/**
* A shortcut method for stampit().deepProperties()
*
* Take a variable number of objects and deeply merge them to any future created instance of the Stamp. Creates and returns a new Stamp.
* @template Obj The type of the object instance being produced by the `Stamp`. or the type of the `Stamp` being created.
* @param deepObjects The object(s) to deeply merge for each new object
* @returns A new Stamp
*/
function deepProperties(...deepObjects: Array<{}>): Stamp;
// tslint:disable-next-line: no-unnecessary-generics
function deepProperties<Obj = any>(...deepObjects: PropertyMap[]): StampType<Obj>;
/**
* A shortcut method for stampit().init()
* @param functions Initializer functions used to create private data and
* privileged methods
* @returns A new stamp
* A shortcut method for stampit().deepProps()
*
* Take a variable number of objects and deeply merge them to any future created instance of the Stamp. Creates and returns a new Stamp.
* @template Obj The type of the object instance being produced by the `Stamp`. or the type of the `Stamp` being created.
* @param deepObjects The object(s) to deeply merge for each new object
*/
function init(...functions: Init[]): Stamp;
/**
* A shortcut method for stampit().init()
* @param functions Initializer functions used to create private data and
* privileged methods
* @returns A new stamp
*/
function init(functions: Init[]): Stamp;
// tslint:disable-next-line: no-unnecessary-generics
function deepProps<Obj = any>(...deepObjects: PropertyMap[]): StampType<Obj>;
/**
* A shortcut method for stampit().initializers()
* @param functions Initializer functions used to create private data and
* privileged methods
* @returns A new stamp
*
* Take in a variable number of functions and add them to the initializers prototype as initializers. **Chainable**.
* @template Obj The type of the object instance being produced by the `Stamp`. or the type of the `Stamp` being created.
* @param functions Initializer functions used to create private data and privileged methods
*/
function initializers(...functions: Init[]): Stamp;
function initializers<Obj = any, S̤t̤a̤m̤p̤ extends StampSignature = StampType<Obj>>(
// tslint:disable-next-line: no-unnecessary-generics
...functions: Array<Initializer<StampObjectType<Obj>, S̤t̤a̤m̤p̤>>
): S̤t̤a̤m̤p̤;
function initializers<Obj = any, S̤t̤a̤m̤p̤ extends StampSignature = StampType<Obj>>(
// tslint:disable-next-line: no-unnecessary-generics
functions: Array<Initializer<StampObjectType<Obj>, S̤t̤a̤m̤p̤>>,
): S̤t̤a̤m̤p̤;
/**
* A shortcut method for stampit().initializers()
* @param functions Initializer functions used to create private data and
* privileged methods
* @returns A new stamp
* A shortcut method for stampit().init()
*
* Take in a variable number of functions and add them to the initializers prototype as initializers. **Chainable**.
* @template Obj The type of the object instance being produced by the `Stamp`. or the type of the `Stamp` being created.
* @param functions Initializer functions used to create private data and privileged methods
*/
function initializers(functions: Init[]): Stamp;
function init<Obj = any, S̤t̤a̤m̤p̤ extends StampSignature = StampType<Obj>>(
// tslint:disable-next-line: no-unnecessary-generics
...functions: Array<Initializer<StampObjectType<Obj>, S̤t̤a̤m̤p̤>>
): S̤t̤a̤m̤p̤;
function init<Obj = any, S̤t̤a̤m̤p̤ extends StampSignature = StampType<Obj>>(
// tslint:disable-next-line: no-unnecessary-generics
functions: Array<Initializer<StampObjectType<Obj>, S̤t̤a̤m̤p̤>>,
): S̤t̤a̤m̤p̤;
/**
* A shortcut method for stampit().statics()
*
* Take n objects and add them to a new stamp and any future stamp it composes with. Creates and returns new Stamp. **Chainable**.
* @template Obj The type of the object instance being produced by the `Stamp`. or the type of the `Stamp` being created.
* @param statics Object(s) containing map of property names and values to mixin into each new stamp.
* @return A new Stamp.
*/
function statics(...statics: Array<{}>): Stamp;
// tslint:disable-next-line: no-unnecessary-generics
function staticProperties<Obj = any>(...statics: PropertyMap[]): StampType<Obj>;
/**
* A shortcut method for stampit().staticProperties()
*
* Take n objects and add them to a new stamp and any future stamp it composes with. Creates and returns new Stamp. **Chainable**.
* @template Obj The type of the object instance being produced by the `Stamp`. or the type of the `Stamp` being created.
* @param statics Object(s) containing map of property names and values to mixin into each new stamp.
* @return A new Stamp.
*/
function staticProperties(...statics: Array<{}>): Stamp;
/**
* A shortcut method for stampit().deepStatics()
* @param deepStatics The object(s) containing static properties to be
* merged
* @returns A new stamp
*/
function deepStatics(...deepStatics: Array<{}>): Stamp;
// tslint:disable-next-line: no-unnecessary-generics
function statics<Obj = any>(...statics: PropertyMap[]): StampType<Obj>;
/**
* A shortcut method for stampit().staticDeepProperties()
* @param deepStatics The object(s) containing static properties to be
* merged
* @returns A new stamp
*
* Deeply merge a variable number of objects and add them to a new stamp and any future stamp it composes. Creates and returns a new Stamp. **Chainable**.
* @template Obj The type of the object instance being produced by the `Stamp`. or the type of the `Stamp` being created.
* @param deepStatics The object(s) containing static properties to be merged
*/
function staticDeepProperties(...deepStatics: Array<{}>): Stamp;
// tslint:disable-next-line: no-unnecessary-generics
function staticDeepProperties<Obj = any>(...deepStatics: PropertyMap[]): StampType<Obj>;
/**
* A shortcut method for stampit().conf()
* @param confs The object(s) containing metadata properties
* @returns A new Stamp
* A shortcut method for stampit().deepStatics()
*
* Deeply merge a variable number of objects and add them to a new stamp and any future stamp it composes. Creates and returns a new Stamp. **Chainable**.
* @template Obj The type of the object instance being produced by the `Stamp`. or the type of the `Stamp` being created.
* @param deepStatics The object(s) containing static properties to be merged
*/
function conf(...confs: Array<{}>): Stamp;
// tslint:disable-next-line: no-unnecessary-generics
function deepStatics<Obj = any>(...deepStatics: PropertyMap[]): StampType<Obj>;
/**
* A shortcut method for stampit().composers()
*
* Take in a variable number of functions and add them to the composers prototype as composers. **Chainable**.
* @template Obj The type of the object instance being produced by the `Stamp`. or the type of the `Stamp` being created.
* @param functions Composer functions that will run in sequence while creating a new stamp from a list of composables. The resulting stamp and the composables get passed to composers.
*/
function composers<Obj = any>(...functions: Array<Composer<StampType<Obj>>>): StampType<Obj>;
function composers<Obj = any>(functions: Array<Composer<StampType<Obj>>>): StampType<Obj>;
/**
* A shortcut method for stampit().configuration()
*
* Shallowly assign properties of Stamp arbitrary metadata and add them to a new stamp and any future Stamp it composes. Creates and returns a new Stamp. **Chainable**.
* @template Obj The type of the object instance being produced by the `Stamp`. or the type of the `Stamp` being created.
* @param confs The object(s) containing metadata properties
* @returns A new Stamp
*/
function configuration(...confs: Array<{}>): Stamp;
// tslint:disable-next-line: no-unnecessary-generics
function configuration<Obj = any>(...confs: PropertyMap[]): StampType<Obj>;
/**
* A shortcut method for stampit().deepConf()
* @param deepConfs The object(s) containing metadata properties
* @returns A new Stamp
* A shortcut method for stampit().conf()
*
* Shallowly assign properties of Stamp arbitrary metadata and add them to a new stamp and any future Stamp it composes. Creates and returns a new Stamp. **Chainable**.
* @template Obj The type of the object instance being produced by the `Stamp`. or the type of the `Stamp` being created.
* @param confs The object(s) containing metadata properties
*/
function deepConf(...deepConfs: Array<{}>): Stamp;
// tslint:disable-next-line: no-unnecessary-generics
function conf<Obj = any>(...confs: PropertyMap[]): StampType<Obj>;
/**
* A shortcut method for stampit().deepConfiguration()
*
* Deeply merge properties of Stamp arbitrary metadata and add them to a new Stamp and any future Stamp it composes. Creates and returns a new Stamp. **Chainable**.
* @template Obj The type of the object instance being produced by the `Stamp`. or the type of the `Stamp` being created.
* @param deepConfs The object(s) containing metadata properties
* @returns A new Stamp
*/
function deepConfiguration(...deepConfs: Array<{}>): Stamp;
// tslint:disable-next-line: no-unnecessary-generics
function deepConfiguration<Obj = any>(...deepConfs: PropertyMap[]): StampType<Obj>;
/**
* A shortcut method for stampit().deepConf()
*
* Deeply merge properties of Stamp arbitrary metadata and add them to a new Stamp and any future Stamp it composes. Creates and returns a new Stamp. **Chainable**.
* @template Obj The type of the object instance being produced by the `Stamp`. or the type of the `Stamp` being created.
* @param deepConfs The object(s) containing metadata properties
*/
// tslint:disable-next-line: no-unnecessary-generics
function deepConf<Obj = any>(...deepConfs: PropertyMap[]): StampType<Obj>;
/**
* A shortcut method for stampit().propertyDescriptors()
*
* Apply ES5 property descriptors to object instances created by the new Stamp returned by the function and any future Stamp it composes. Creates and returns a new stamp. **Chainable**.
* @template Obj The type of the object instance being produced by the `Stamp`. or the type of the `Stamp` being created.
* @param descriptors
* @returns A new Stamp
*/
function propertyDescriptors(...descriptors: Array<{}>): Stamp;
// tslint:disable-next-line: no-unnecessary-generics
function propertyDescriptors<Obj = any>(...descriptors: PropertyDescriptorMap[]): StampType<Obj>;
/**
* A shortcut method for stampit().staticPropertyDescriptors()
*
* Apply ES5 property descriptors to a Stamp and any future Stamp it composes. Creates and returns a new stamp. **Chainable**.
* @template Obj The type of the object instance being produced by the `Stamp`. or the type of the `Stamp` being created.
* @param descriptors
* @returns A new Stamp
*/
function staticPropertyDescriptors(...descriptors: Array<{}>): Stamp;
// tslint:disable-next-line: no-unnecessary-generics
function staticPropertyDescriptors<Obj = any>(...descriptors: PropertyDescriptorMap[]): StampType<Obj>;
/**
* Take two or more Composables and combine them to produce a new Stamp.
* Combining overrides properties with last-in priority.
* @param composables Composable objects used to create the stamp.
* @return A new Stamp made of all the given composables.
*/
function compose(...composables: Composable[]): Stamp;
/** A function which creates a new `Stamp`s from a list of `Composable`s. */
const compose: ComposeMethod;
/** the version of the NPM `stampit` package. */
const version: string;
}
export = stampit;
export const compose: typeof stampit.compose;
export const composers: typeof stampit.composers;
export const conf: typeof stampit.conf;
export const configuration: typeof stampit.configuration;
export const deepConf: typeof stampit.deepConf;
export const deepConfiguration: typeof stampit.deepConfiguration;
export const deepProperties: typeof stampit.deepProperties;
export const deepProps: typeof stampit.deepProps;
export const deepStatics: typeof stampit.deepStatics;
export const init: typeof stampit.init;
export const initializers: typeof stampit.initializers;
export const methods: typeof stampit.methods;
export const properties: typeof stampit.properties;
export const propertyDescriptors: typeof stampit.propertyDescriptors;
export const props: typeof stampit.props;
export const staticDeepProperties: typeof stampit.staticDeepProperties;
export const staticProperties: typeof stampit.staticProperties;
export const staticPropertyDescriptors: typeof stampit.staticPropertyDescriptors;
export const version: typeof stampit.version;
// tslint:disable-next-line: npm-naming
export default stampit;

View File

@ -1,4 +1,31 @@
import stampit = require('stampit');
/** Import 'stampit' module */
import stampit from 'stampit';
/** Import 'stampit' as ... module */
// import * as Stamp from 'stampit';
/** selective import from module */
// import {
// compose,
// composers,
// conf,
// configuration,
// deepConf,
// deepConfiguration,
// deepProperties,
// deepProps,
// deepStatics,
// init,
// initializers,
// methods,
// properties,
// propertyDescriptors,
// props,
// staticDeepProperties,
// staticProperties,
// staticPropertyDescriptors,
// version,
// } from 'stampit';
const a = stampit().init(function(options) {
const a = options.args[0];
@ -21,10 +48,16 @@ const foo = c(); // we won't throw this one away...
foo.getA(); // "a"
foo.getB(); // "b"
// Here's a mixin with public methods, and some refs:
// Here's a mixin with public methods, and some props:
const membership = stampit({
methods: {
members: {},
members: {
itCanBe: "anything",
},
myMembers: {},
dbConnString: "pgs://data.local",
MY_LIMIT: 100,
myRegExp: /foobar/g,
add(member: any) {
this.members[member.name] = member;
return this;
@ -33,13 +66,13 @@ const membership = stampit({
return this.members[name];
}
},
refs: {
props: {
members: {}
}
});
// Let's set some defaults:
const defaults = stampit().refs({
const defaults = stampit().props({
name: 'The Saloon',
specials: 'Whisky, Gin, Tequila'
});
@ -47,7 +80,7 @@ const defaults = stampit().refs({
// Classical inheritance has nothing on this. No parent/child coupling. No deep inheritance hierarchies.
// Just good, clean code reusability.
const bar = stampit.compose(defaults, membership);
// Note that you can override refs on instantiation:
// Note that you can override props on instantiation:
const myBar = bar({ name: 'Moe\'s' });
// Silly, but proves that everything is as it should be.
myBar.add({ name: 'Homer' }).open().getMember('Homer');
@ -58,20 +91,28 @@ const myStamp = stampit().methods({
},
methodOverride() {
return false;
}
},
myMembers: {},
dbConnString: "pgs://data.local",
MY_LIMIT: 100,
myRegExp: /foobar/g,
}).methods({
bar() {
return 'bar';
},
methodOverride() {
return true;
}
},
myMembers: {},
dbConnString: "pgs://data.local",
MY_LIMIT: 100,
myRegExp: /foobar/g,
});
myStamp.props({
myStamp.deepProps({
foo: { bar: 'bar' },
refsOverride: false
}).refs({
}).props({
bar: 'bar',
refsOverride: true
});
@ -93,19 +134,27 @@ myStamp.init(function() {
let obj = myStamp.create();
obj.getSecret && obj.a && obj.b && obj.c; // true
const newStamp = stampit({ refs: { defaultNum: 1 } }).compose(myStamp);
const newStamp = stampit({ props: { defaultNum: 1 } }).compose(myStamp);
const obj1 = stampit().methods({
a() {
return 'a';
}
},
myMembers: {},
dbConnString: "pgs://data.local",
MY_LIMIT: 100,
myRegExp: /foobar/g,
}, {
b() {
return 'b';
}
},
myMembers: {},
dbConnString: "pgs://data.local",
MY_LIMIT: 100,
myRegExp: /foobar/g,
}).create();
const obj2 = stampit().refs({
const obj2 = stampit().props({
a: 'a'
}, {
b: 'b'
@ -125,7 +174,11 @@ Constructor.prototype.foo = function foo() {
const newskool = stampit().methods({
bar: function bar() {
return 'bar';
}
},
myMembers: {},
dbConnString: "pgs://data.local",
MY_LIMIT: 100,
myRegExp: /foobar/g,
// your methods here...
}).init(function() {
this.baz = 'baz';
@ -149,15 +202,139 @@ interface SomeStampInstance {
}
// Test import of stamp type
interface SomeStamp extends stampit.Stamp {
interface SomeStamp extends stampit.Stamp<SomeStampInstance> {
(params: { a: number; b: boolean}): SomeStampInstance;
}
const SomeStamp = stampit()
const SomeStamp = stampit<SomeStamp>()
.init(function(params: { a: number; b: boolean}) {
this.a = '' + a;
this.a = '' + a; // this SomeStampInstance
this.b = '' + b;
}) as SomeStamp;
});
SomeStamp({ a: 1, b: false }); // $ExpectType SomeStampInstance
SomeStamp({ a: 1, b: false }).a; // $ExpectType string
const d: stampit.ExtendedDescriptor<{}> = {
methods: {},
properties: {},
deepProperties: {},
propertyDescriptors: {},
initializers: [],
staticProperties: {},
staticDeepProperties: {},
staticPropertyDescriptors: {},
composers: [],
configuration: {},
deepConfiguration: {},
name: '',
// shorthands
props: {},
deepProps: {},
init: [],
statics: {},
deepStatics: {},
conf: {},
deepConf: {},
};
// The `.compose()` method
const compose = stampit.compose; // $ExpectType typeof stampit
const stampUntyped = compose(); // $ExpectType Stamp<any>
stampUntyped(); // $ExpectType any
// const stampAny = compose<any>(); // $ExpectType Stamp<any>
// stampAny(); // $ExpectType any
const stampBigint = compose<bigint>(); // $ExpectType never
const stampBoolean = compose<boolean>(); // $ExpectType never
const stampNull = compose<null>(); // $ExpectType never
const stampNumber = compose<number>(); // $ExpectType never
const stampString = compose<string>(); // $ExpectType never
const stampSymbol = compose<symbol>(); // $ExpectType never
const stampUndefined = compose<undefined>(); // $ExpectType never
const stampUnknown = compose<unknown>(); // $ExpectType Stamp<unknown>
stampUnknown(); // $ExpectType unknown
const stampNever = compose<never>(); // $ExpectType never
// Declare interface of objects created by stamps
interface Object0 {
action: () => void;
value: number;
}
interface Object1 {
reaction: () => void;
property: number;
}
const stampObject0 = compose<Object0>(); // $ExpectType Stamp<Object0>
stampObject0(); // $ExpectType Object0
const stampObject1 = compose<Object1>(); // $ExpectType Stamp<Object1>
stampObject1(); // $ExpectType Object1
// Define a typed ExtendedDescriptor and benefit its properly typed `this` in `methods`
const descriptor0: stampit.ExtendedDescriptor<Object0> = {
methods: {
logLocalThis() {
this; // $ExpectType Object0
},
myMembers: {},
dbConnString: "pgs://data.local",
MY_LIMIT: 100,
myRegExp: /foobar/g,
},
properties: {},
deepProperties: {},
propertyDescriptors: {},
staticProperties: {},
staticDeepProperties: {},
staticPropertyDescriptors: {},
initializers: [
function(options, context) {
this; // $ExpectType Object0
return context.instance;
}
],
composers: [
(parameters) => {
return parameters.stamp;
}
],
configuration: {},
deepConfiguration: {}
};
const stampDescriptor0 = compose<typeof descriptor0>(descriptor0); // $ExpectType Stamp<Object0>
stampDescriptor0(); // $ExpectType Object0
// check typed stamps... with untyped descriptor (`this` isn't typed in `methods`)
// inline type assertion is still possible though
const stampUntypedDescriptor0 = compose<Object0>(/* <stampit.ExtendedDescriptor<Object0>> */ {
methods: {
logLocalThis() {
this; // $ExpectType any
},
myMembers: {},
dbConnString: "pgs://data.local",
MY_LIMIT: 100,
myRegExp: /foobar/g,
},
} /* as stampit.ExtendedDescriptor<Object0> */);
stampUntypedDescriptor0; // $ExpectType Stamp<Object0>
stampUntypedDescriptor0(); // $ExpectType Object0
// Check a stamp's `.compose()` method
const stamp1 = stampObject0.compose<Object1>(); // $ExpectType Stamp<Object1>
stamp1(); // $ExpectType Object1
// Define an extended stamp.
// The type of created object cannot be changed afterward
// Lazy interface composition can be done using the `&` intersection operator
interface ExtendedStamp extends stampit.Stamp<Object0 & Object1> {
decompose: () => unknown;
}
// Invoke `.compose()` method with the type of the extended stamp
const extendedStamp0 = compose<ExtendedStamp>(); // $ExpectType ExtendedStamp
extendedStamp0(); // $ExpectType Object0 & Object1

View File

@ -20,4 +20,4 @@
"index.d.ts",
"stampit-tests.ts"
]
}
}

View File

@ -1,3 +1,3 @@
{
"extends": "dtslint/dt.json"
}
}

518
types/stampit/v3/index.d.ts vendored Normal file
View File

@ -0,0 +1,518 @@
// Type definitions for stampit 3.0
// Project: https://github.com/stampit-org/stampit, https://stampit.js.org
// Definitions by: Vasyl Boroviak <https://github.com/koresar>
// Harris Lummis <https://github.com/lummish>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
/**
* Function used as .init() argument.
*/
type Init = (factoryArg: any, ctx?: Context) => any;
/**
* Composer function
*/
type Composer = ({ stamp, composables }: { stamp: stampit.Stamp; composables: Composable[] }) => any;
/** The stamp Descriptor */
interface Descriptor {
/** Create a new stamp based on this descriptor */
(...composables: Composable[]): stampit.Stamp;
/**
* A hash containing methods (functions) of any future created instance.
*/
methods?: {};
/**
* Initialization function(s) which will be called per each newly created
* instance.
*/
initializers?: Init[];
/**
* Properties which will shallowly copied into any future created instance.
*/
properties?: {};
/**
* Properties which will be mixed to the new and any other stamp which this stamp will be composed with.
*/
staticProperties?: {};
/** Deeply merged properties of object instances */
deepProperties?: {};
/** ES5 Property Descriptors applied to object instances */
propertyDescriptors?: {};
/** Deeply merged properties of Stamps */
staticDeepProperties?: {};
/** ES5 Property Descriptors applied to Stamps */
staticPropertyDescriptors?: {};
/** A configuration object to be shallowly assigned to Stamps */
configuration?: {};
/** A configuration object to be deeply merged to Stamps */
deepConfiguration?: {};
}
/** Any composable object (stamp or descriptor) */
type Composable = stampit.Stamp | Descriptor;
/**
* The .init() function argument.
*/
interface Context {
/**
* The object which has been just instantiated.
*/
instance: any;
/**
* The stamp the object has been instantiated with.
*/
stamp: stampit.Stamp;
/**
* The arguments list passed to the stamp.
*/
args: any[];
}
interface Options {
/**
* A hash containing methods (functions) of any future created instance.
*/
methods?: {};
/**
* Initialization function(s) which will be called per each newly created
* instance.
*/
init?: Init | Init[];
/**
* Initialization function(s) which will be called per each newly created
* instance.
*/
initializers?: Init | Init[];
/**
* Properties which will shallowly copied into any future created instance.
*/
props?: {};
/**
* Properties which will shallowly copied into any future created instance.
*/
properties?: {};
/**
* A hash containing references to the object. This hash will be shallow mixed into any future created instance.
*/
refs?: {};
/**
* Properties which will be mixed to the new and any other stamp which this
* stamp will be composed with.
*/
staticProperties?: {};
/**
* Properties which will be mixed to the new and any other stamp which this
* stamp will be composed with.
*/
statics?: {};
/** Deeply merged properties of object instances */
deepProperties?: {};
/** Deeply merged properties of object instances */
deepProps?: {};
/** ES5 Property Descriptors applied to object instances */
propertyDescriptors?: {};
/** Deeply merged properties of Stamps */
staticDeepProperties?: {};
/** Deeply merged properties of Stamps */
deepStatics?: {};
/** ES5 Property Descriptors applied to Stamps */
staticPropertyDescriptors?: {};
/** A configuration object to be shallowly assigned to Stamps */
configuration?: {};
/** A configuration object to be shallowly assigned to Stamps */
conf?: {};
/** A configuration object to be deeply merged to Stamps */
deepConfiguration?: {};
/** A configuration object to be deeply merged to Stamps */
deepConf?: {};
/** Callback functions to execute each time a composition occurs */
composers?: Composer[];
}
/** Stampit Composable for main stampit() function */
type StampitComposable = stampit.Stamp | Descriptor | Options;
/**
* Return a factory (aka Stamp) function that will produce new objects using the
* prototypes that are passed in or composed.
* @param options Stampit options object containing refs, methods,
* init, props, statics, configurations, and property descriptors.
*/
declare function stampit(...composables: StampitComposable[]): stampit.Stamp;
declare namespace stampit {
/**
* A factory function that will produce new objects using the
* prototypes that are passed in or composed.
*/
interface Stamp {
/**
* Invokes the stamp and returns a new object instance.
* @param state Properties you wish to set on the new objects.
* @param encloseArgs The remaining arguments are passed to all .enclose() functions.
* WARNING Avoid using two different .enclose() functions that expect different arguments.
* .enclose() functions that take arguments should not be considered safe to compose
* with other .enclose() functions that also take arguments. Taking arguments with
* an .enclose() function is an anti-pattern that should be avoided, when possible.
* @return A new object composed of the Stamps and prototypes provided.
*/
(state?: {}, ...encloseArgs: any[]): any;
/**
* Just like calling stamp(), stamp.create() invokes the stamp and returns a new instance.
* @param state Properties you wish to set on the new objects.
* @param encloseArgs The remaining arguments are passed to all .enclose() functions.
* WARNING Avoid using two different .enclose() functions that expect different arguments.
* .enclose() functions that take arguments should not be considered safe to compose
* with other .enclose() functions that also take arguments. Taking arguments with
* an .enclose() function is an anti-pattern that should be avoided, when possible.
* @return A new object composed of the Stamps and prototypes provided.
*/
create(state?: {}, ...encloseArgs: any[]): any;
/**
* Stamp metadata/composer function
*/
compose: Descriptor;
/**
* Add methods to the methods prototype. Creates and returns new Stamp. Chainable.
* @param methods Object(s) containing map of method names and bodies for delegation.
* @return A new Stamp.
*/
methods(...methods: Array<{}>): Stamp;
/**
* Take n objects and add them to the state prototype. Creates and returns new Stamp. Chainable.
* @param states Object(s) containing map of property names and values to clone for each new object.
* @return A new Stamp.
*/
refs(...states: Array<{}>): Stamp;
/**
* Take a variable number of objects and shallow assign them to any future
* created instance of the Stamp. Creates and returns new Stamp. Chainable.
* @param objects Object(s) to shallow assign for each new object.
* @return A new Stamp.
*/
props(...objects: Array<{}>): Stamp;
/**
* Take a variable number of objects and shallow assign them to any future
* created instance of the Stamp. Creates and returns new Stamp. Chainable.
* @param objects Object(s) to shallow assign for each new object.
* @return A new Stamp.
*/
properties(...objects: Array<{}>): Stamp;
/**
* Take a variable number of objects and deeply merge them to any future
* created instance of the Stamp. Creates and returns a new Stamp.
* Chainable.
* @param deepObjects The object(s) to deeply merge for each new object
* @returns A new Stamp
*/
deepProps(...deepObjects: Array<{}>): Stamp;
/**
* Take a variable number of objects and deeply merge them to any future
* created instance of the Stamp. Creates and returns a new Stamp.
* Chainable.
* @param deepObjects The object(s) to deeply merge for each new object
* @returns A new Stamp
*/
deepProperties(...deepObjects: Array<{}>): Stamp;
/**
* @deprecated Use .init() instead.
*/
enclose(...functions: Init[]): Stamp;
/**
* @deprecated Use .init() instead.
*/
enclose(...functions: Array<{}>): Stamp;
/**
* Take in a variable number of functions and add them to the enclose
* prototype as initializers.
* @param functions Initializer functions used to create private data and
* privileged methods
* @returns A new stamp
*/
init(...functions: Init[]): Stamp;
/**
* Take in a variable number of functions and add them to the enclose
* prototype as initializers.
* @param functions Initializer functions used to create private data and
* privileged methods
* @returns A new stamp
*/
init(functions: Init[]): Stamp;
/**
* Take in a variable number of functions and add them to the enclose
* prototype as initializers.
* @param functions Initializer functions used to create private data and
* privileged methods
* @returns A new stamp
*/
initializers(...functions: Init[]): Stamp;
/**
* Take in a variable number of functions and add them to the enclose
* prototype as initializers.
* @param functions Initializer functions used to create private data and
* privileged methods
* @returns A new stamp
*/
initializers(functions: Init[]): Stamp;
/**
* Take n objects and add them to a new stamp and any future stamp it composes with.
* Creates and returns new Stamp. Chainable.
* @param statics Object(s) containing map of property names and values to mixin into each new stamp.
* @return A new Stamp.
*/
statics(...statics: Array<{}>): Stamp;
/**
* Take n objects and add them to a new stamp and any future stamp it composes with.
* Creates and returns new Stamp. Chainable.
* @param statics Object(s) containing map of property names and values to mixin into each new stamp.
* @return A new Stamp.
*/
staticProperties(...statics: Array<{}>): Stamp;
/**
* Deeply merge a variable number of objects and add them to a new stamp and
* any future stamp it composes. Creates and returns a new Stamp. Chainable.
* @param deepStatics The object(s) containing static properties to be
* merged
* @returns A new stamp
*/
deepStatics(...deepStatics: Array<{}>): Stamp;
/**
* Deeply merge a variable number of objects and add them to a new stamp and
* any future stamp it composes. Creates and returns a new Stamp. Chainable.
* @param deepStatics The object(s) containing static properties to be
* merged
* @returns A new stamp
*/
staticDeepProperties(...deepStatics: Array<{}>): Stamp;
/**
* Shallowly assign properties of Stamp arbitrary metadata and add them to
* a new stamp and any future Stamp it composes. Creates and returns a new
* Stamp. Chainable.
* @param confs The object(s) containing metadata properties
* @returns A new Stamp
*/
conf(...confs: Array<{}>): Stamp;
/**
* Shallowly assign properties of Stamp arbitrary metadata and add them to
* a new stamp and any future Stamp it composes. Creates and returns a new
* Stamp. Chainable.
* @param confs The object(s) containing metadata properties
* @returns A new Stamp
*/
configuration(...confs: Array<{}>): Stamp;
/**
* Deeply merge properties of Stamp arbitrary metadata and add them to a new
* Stamp and any future Stamp it composes. Creates and returns a new Stamp.
* Chainable.
* @param deepConfs The object(s) containing metadata properties
* @returns A new Stamp
*/
deepConf(...deepConfs: Array<{}>): Stamp;
/**
* Deeply merge properties of Stamp arbitrary metadata and add them to a new
* Stamp and any future Stamp it composes. Creates and returns a new Stamp.
* Chainable.
* @param deepConfs The object(s) containing metadata properties
* @returns A new Stamp
*/
deepConfiguration(...deepConfs: Array<{}>): Stamp;
/**
* Apply ES5 property descriptors to object instances created by the new
* Stamp returned by the function and any future Stamp it composes. Creates
* and returns a new stamp. Chainable.
* @param descriptors
* @returns A new Stamp
*/
propertyDescriptors(...descriptors: Array<{}>): Stamp;
/**
* Apply ES5 property descriptors to a Stamp and any future Stamp it
* composes. Creates and returns a new stamp. Chainable.
* @param descriptors
* @returns A new Stamp
*/
staticPropertyDescriptors(...descriptors: Array<{}>): Stamp;
}
/**
* A shortcut methods for stampit().methods()
* @param methods Object(s) containing map of method names and bodies for delegation.
* @return A new Stamp.
*/
function methods(...methods: Array<{}>): Stamp;
/**
* A shortcut methods for stampit().refs()
* @param states Object(s) containing map of property names and values to clone for each new object.
* @return A new Stamp.
*/
function refs(...states: Array<{}>): Stamp;
/**
* A shortcut method for stampit().props()
* @param objects Object(s) to shallow assign for each new object.
* @return A new Stamp.
*/
function props(...objects: Array<{}>): Stamp;
/**
* A shortcut method for stampit().properties()
* @param objects Object(s) to shallow assign for each new object.
* @return A new Stamp.
*/
function properties(...objects: Array<{}>): Stamp;
/**
* A shortcut method for stampit().deepProps()
* @param deepObjects The object(s) to deeply merge for each new object
* @returns A new Stamp
*/
function deepProps(...deepObjects: Array<{}>): Stamp;
/**
* A shortcut method for stampit().deepProperties()
* @param deepObjects The object(s) to deeply merge for each new object
* @returns A new Stamp
*/
function deepProperties(...deepObjects: Array<{}>): Stamp;
/**
* A shortcut method for stampit().init()
* @param functions Initializer functions used to create private data and
* privileged methods
* @returns A new stamp
*/
function init(...functions: Init[]): Stamp;
/**
* A shortcut method for stampit().init()
* @param functions Initializer functions used to create private data and
* privileged methods
* @returns A new stamp
*/
function init(functions: Init[]): Stamp;
/**
* A shortcut method for stampit().initializers()
* @param functions Initializer functions used to create private data and
* privileged methods
* @returns A new stamp
*/
function initializers(...functions: Init[]): Stamp;
/**
* A shortcut method for stampit().initializers()
* @param functions Initializer functions used to create private data and
* privileged methods
* @returns A new stamp
*/
function initializers(functions: Init[]): Stamp;
/**
* A shortcut method for stampit().statics()
* @param statics Object(s) containing map of property names and values to mixin into each new stamp.
* @return A new Stamp.
*/
function statics(...statics: Array<{}>): Stamp;
/**
* A shortcut method for stampit().staticProperties()
* @param statics Object(s) containing map of property names and values to mixin into each new stamp.
* @return A new Stamp.
*/
function staticProperties(...statics: Array<{}>): Stamp;
/**
* A shortcut method for stampit().deepStatics()
* @param deepStatics The object(s) containing static properties to be
* merged
* @returns A new stamp
*/
function deepStatics(...deepStatics: Array<{}>): Stamp;
/**
* A shortcut method for stampit().staticDeepProperties()
* @param deepStatics The object(s) containing static properties to be
* merged
* @returns A new stamp
*/
function staticDeepProperties(...deepStatics: Array<{}>): Stamp;
/**
* A shortcut method for stampit().conf()
* @param confs The object(s) containing metadata properties
* @returns A new Stamp
*/
function conf(...confs: Array<{}>): Stamp;
/**
* A shortcut method for stampit().configuration()
* @param confs The object(s) containing metadata properties
* @returns A new Stamp
*/
function configuration(...confs: Array<{}>): Stamp;
/**
* A shortcut method for stampit().deepConf()
* @param deepConfs The object(s) containing metadata properties
* @returns A new Stamp
*/
function deepConf(...deepConfs: Array<{}>): Stamp;
/**
* A shortcut method for stampit().deepConfiguration()
* @param deepConfs The object(s) containing metadata properties
* @returns A new Stamp
*/
function deepConfiguration(...deepConfs: Array<{}>): Stamp;
/**
* A shortcut method for stampit().propertyDescriptors()
* @param descriptors
* @returns A new Stamp
*/
function propertyDescriptors(...descriptors: Array<{}>): Stamp;
/**
* A shortcut method for stampit().staticPropertyDescriptors()
* @param descriptors
* @returns A new Stamp
*/
function staticPropertyDescriptors(...descriptors: Array<{}>): Stamp;
/**
* Take two or more Composables and combine them to produce a new Stamp.
* Combining overrides properties with last-in priority.
* @param composables Composable objects used to create the stamp.
* @return A new Stamp made of all the given composables.
*/
function compose(...composables: Composable[]): Stamp;
}
export = stampit;

View File

@ -0,0 +1,163 @@
import stampit = require('stampit');
const a = stampit().init(function(options) {
const a = options.args[0];
this.getA = () => {
return a;
};
});
a(); // Object -- so far so good.
a().getA(); // "a"
const b = stampit().init(function() {
const a = 'b';
this.getB = () => {
return a;
};
});
const c = stampit.compose(a, b);
const foo = c(); // we won't throw this one away...
foo.getA(); // "a"
foo.getB(); // "b"
// Here's a mixin with public methods, and some refs:
const membership = stampit({
methods: {
members: {},
add(member: any) {
this.members[member.name] = member;
return this;
},
getMember(name: any) {
return this.members[name];
}
},
refs: {
members: {}
}
});
// Let's set some defaults:
const defaults = stampit().refs({
name: 'The Saloon',
specials: 'Whisky, Gin, Tequila'
});
// Classical inheritance has nothing on this. No parent/child coupling. No deep inheritance hierarchies.
// Just good, clean code reusability.
const bar = stampit.compose(defaults, membership);
// Note that you can override refs on instantiation:
const myBar = bar({ name: 'Moe\'s' });
// Silly, but proves that everything is as it should be.
myBar.add({ name: 'Homer' }).open().getMember('Homer');
const myStamp = stampit().methods({
foo() {
return 'foo';
},
methodOverride() {
return false;
}
}).methods({
bar() {
return 'bar';
},
methodOverride() {
return true;
}
});
myStamp.props({
foo: { bar: 'bar' },
refsOverride: false
}).refs({
bar: 'bar',
refsOverride: true
});
myStamp.init(function() {
const secret = 'foo';
this.getSecret = () => {
return secret;
};
}).init(function() {
this.a = true;
}).init(function() {
this.b = true;
}, function() {
this.c = true;
});
let obj = myStamp.create();
obj.getSecret && obj.a && obj.b && obj.c; // true
const newStamp = stampit({ refs: { defaultNum: 1 } }).compose(myStamp);
const obj1 = stampit().methods({
a() {
return 'a';
}
}, {
b() {
return 'b';
}
}).create();
const obj2 = stampit().refs({
a: 'a'
}, {
b: 'b'
}).create();
obj = defaults.compose(newStamp, membership).create();
// The old constructor / class thing...
const Constructor = function Constructor() {
this.thing = 'initialized';
};
Constructor.prototype.foo = function foo() {
return 'foo';
};
// A new stamp to compose with...
const newskool = stampit().methods({
bar: function bar() {
return 'bar';
}
// your methods here...
}).init(function() {
this.baz = 'baz';
});
// Now you can compose those old constructors just like you could
// with any other stamp...
const myThing = stampit.compose(newskool);
const t = myThing();
t.thing; // 'initialized',
t.foo(); // 'foo',
t.bar(); // 'bar'
interface SomeStampInstance {
a: string;
b: string;
}
// Test import of stamp type
interface SomeStamp extends stampit.Stamp {
(params: { a: number; b: boolean}): SomeStampInstance;
}
const SomeStamp = stampit()
.init(function(params: { a: number; b: boolean}) {
this.a = '' + a;
this.b = '' + b;
}) as SomeStamp;
SomeStamp({ a: 1, b: false }); // $ExpectType SomeStampInstance
SomeStamp({ a: 1, b: false }).a; // $ExpectType string

View File

@ -0,0 +1,28 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": false,
"strictNullChecks": false,
"strictFunctionTypes": true,
"baseUrl": "../../",
"typeRoots": [
"../../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true,
"paths": {
"stampit": [
"stampit/v3"
]
}
},
"files": [
"index.d.ts",
"stampit-tests.ts"
]
}

View File

@ -0,0 +1,3 @@
{
"extends": "dtslint/dt.json"
}