This repository has been archived by the owner on Feb 26, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
g. nicholas d'andrea
committed
Aug 18, 2021
1 parent
4d2cff7
commit 375a5e1
Showing
4 changed files
with
251 additions
and
136 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,35 @@ | ||
/** | ||
* An object of type Constructor<S> is a JS constructor (or "class") that | ||
* takes a sole argument (of the specified "options" type), and instantiates | ||
* a new object in memory (of the specified "result" type). | ||
*/ | ||
export type Constructor<S extends Constructor.Specification> = new ( | ||
options: Constructor.Options<S> | ||
) => Constructor.Result<S>; | ||
|
||
export namespace Constructor { | ||
/** | ||
* Type-level description for a particular constructor | ||
*/ | ||
export type Specification = { | ||
/** | ||
* Options argument for specified constructor | ||
* The type of the sole `options` argument passed to the constructor | ||
*/ | ||
options: any; | ||
|
||
/** | ||
* Output object created by specified constructor | ||
* The type of the object the constructor creates | ||
*/ | ||
result: any; | ||
}; | ||
|
||
/** | ||
* Getter type for constructor arg | ||
* The `options` type for the specified constructor. | ||
*/ | ||
export type Options<S extends Specification> = S["options"]; | ||
|
||
/** | ||
* Getter type for constructed object | ||
* The type of the object created by the specified constructor. | ||
*/ | ||
export type Result<S extends Specification> = S["result"]; | ||
} | ||
|
||
/** | ||
* An object of type Constructor<S> is a JS constructor (or "class") that | ||
* takes a sole argument (of the specified "options" type), and instantiates | ||
* a new object in memory (of the specified "result" type). | ||
*/ | ||
export type Constructor<S extends Constructor.Specification> = new ( | ||
options: Constructor.Options<S> | ||
) => Constructor.Result<S>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,25 @@ | ||
export namespace Results { | ||
export type Specification = { | ||
/** | ||
* When specifying results, the `load` type represents the return value for | ||
* a `load()` method. | ||
*/ | ||
load: any; | ||
|
||
/** | ||
* When specifying results, the `load` type represents the return value for | ||
* a `list()` method. | ||
*/ | ||
list: any; | ||
}; | ||
|
||
/** | ||
* The type returned by `load()` according to the results specification. | ||
*/ | ||
export type Load<S extends Specification> = S["load"]; | ||
|
||
/** | ||
* The type returned by `list()` according to the results specification. | ||
*/ | ||
export type List<S extends Specification> = S["list"]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,106 +1,163 @@ | ||
import type { Constructor as FreeConstructor } from "./constructor"; | ||
import type { Results as FreeResults } from "./results"; | ||
|
||
/** | ||
* An object of type Strategy<S> provides version loading and possibly version | ||
* listing functionality | ||
* | ||
* Note that a valid Strategy.Specification must include `true` or `false` for | ||
* `allowsLoadingSpecificVersion` and `allowsListingVersions` types, otherwise | ||
* Strategy<S> may not be well-formed. These types are used as flags to | ||
* determine the correct method signatures for the strategy. | ||
*/ | ||
export type Strategy<S extends Strategy.Specification> = BaseStrategy<S> & | ||
(true extends Strategy.AllowsLoadingSpecificVersion<S> | ||
? { | ||
load(version?: string): Strategy.Results.Load<S>; | ||
} | ||
: { | ||
load(): Strategy.Results.Load<S>; | ||
}) & | ||
(true extends Strategy.AllowsListingVersions<S> | ||
? { | ||
list(): Strategy.Results.List<S>; | ||
} | ||
: {}); | ||
|
||
/** | ||
* An object of BaseStrategy<S> allows loading an unspecified version, plus | ||
* type guards to determine additional functionality | ||
*/ | ||
export interface BaseStrategy<S extends Strategy.Specification> { | ||
load(): Strategy.Results.Load<S>; | ||
|
||
allowsLoadingSpecificVersion(): this is this & { | ||
load(version?: string): Strategy.Results.Load<S>; | ||
}; | ||
|
||
allowsListingVersions(): this is { | ||
list(): Strategy.Results.List<S>; | ||
}; | ||
} | ||
|
||
export namespace Strategy { | ||
/** | ||
* Type-level description of a supplier strategy | ||
*/ | ||
export type Specification = { | ||
/** | ||
* A strategy specification includes a constructor specification, minus | ||
* the constructor specification's `result` property, since this module | ||
* will inherently deal in constructors that result in an instance of | ||
* the specified Strategy. | ||
*/ | ||
constructor: Omit<FreeConstructor.Specification, "result">; | ||
|
||
/** | ||
* A strategy specification includes a `results` specification, | ||
* defining the types returned for `load()` and `list()` methods. | ||
*/ | ||
results: FreeResults.Specification; | ||
|
||
/** | ||
* A strategy specifies whether it allows loading specific versions. | ||
* | ||
* When specifying a strategy, this must be `true` or `false` explicitly. | ||
*/ | ||
allowsLoadingSpecificVersion: boolean; | ||
|
||
/** | ||
* A strategy specifies whether it allows listing versions. | ||
* | ||
* When specifying a strategy, this must be `true` or `false` explicitly. | ||
*/ | ||
allowsListingVersions: boolean; | ||
}; | ||
|
||
/** | ||
* Type representing a constructor for specified strategy. | ||
* | ||
* This re-exports from the constructor module to use Strategy.Specification | ||
* as root. | ||
*/ | ||
export type Constructor<S extends Strategy.Specification> = FreeConstructor< | ||
Strategy.Constructor.Specification<S> | ||
>; | ||
|
||
/** | ||
* Scoped re-exports of Constructor, using Strategy.Specification as | ||
* generic param | ||
*/ | ||
export namespace Constructor { | ||
/** | ||
* Getter for the specified constructor, intersected with fixed result | ||
* type of Strategy<S> | ||
* Type-level specification of the constructor for a given strategy; | ||
* | ||
* Constructor `options` are taken as specified for the strategy, using | ||
* an instance of the specified strategy as the result specification. | ||
*/ | ||
export type Specification<S extends Strategy.Specification> = | ||
S["constructor"] & { result: Strategy<S>; }; | ||
export type Specification< | ||
S extends Strategy.Specification | ||
> = S["constructor"] & { result: Strategy<S> }; | ||
|
||
/** | ||
* Constructor options argument for a specified strategy | ||
* Type representing the `options` argument for constructing the specified | ||
* strategy. | ||
* | ||
* This re-exports from the constructor module to use | ||
* Strategy.Specification as the root. | ||
*/ | ||
export type Options<S extends Strategy.Specification> = FreeConstructor.Options< | ||
Strategy.Constructor.Specification<S> | ||
>; | ||
export type Options< | ||
S extends Strategy.Specification | ||
> = FreeConstructor.Options<Strategy.Constructor.Specification<S>>; | ||
} | ||
|
||
/** | ||
* Type representing a constructor for specified strategy | ||
*/ | ||
export type Constructor<S extends Strategy.Specification> = FreeConstructor< | ||
Strategy.Constructor.Specification<S> | ||
>; | ||
|
||
/** | ||
* Results types for a particular strategy | ||
*/ | ||
export namespace Results { | ||
export type Specification<S extends Strategy.Specification> = | ||
S["results"]; | ||
/** | ||
* Type-level specification of method results for specified strategy | ||
*/ | ||
export type Specification<S extends Strategy.Specification> = S["results"]; | ||
|
||
/** | ||
* Type returned by the strategy's `load()` method. | ||
* | ||
* This re-exports from the results module to use Strategy.Specification | ||
* as the root. | ||
*/ | ||
export type Load<S extends Strategy.Specification> = FreeResults.Load< | ||
Strategy.Results.Specification<S> | ||
>; | ||
|
||
/** | ||
* Type returned by the strategy's `list()` method. | ||
* | ||
* This re-exports from the results module to use Strategy.Specification | ||
* as the root. | ||
*/ | ||
export type List<S extends Strategy.Specification> = FreeResults.List< | ||
Strategy.Results.Specification<S> | ||
>; | ||
} | ||
|
||
/** | ||
* Getter type for whether specified strategy allows argument to load() | ||
* Whether the specified strategy allows loading specific versions. | ||
* | ||
* For a well-specified strategy, this will always be the type literal | ||
* `true` or `false` (never the generalized `boolean`) | ||
*/ | ||
export type AllowsLoadingSpecificVersion< | ||
S extends Strategy.Specification | ||
> = S["allowsLoadingSpecificVersion"]; | ||
|
||
/** | ||
* Getter type for whether specified strategy provides version listing | ||
* Whether the specified strategy allows listing known versions. | ||
* | ||
* For a well-specified strategy, this will always be the type literal | ||
* `true` or `false` (never the generalized `boolean`) | ||
*/ | ||
export type AllowsListingVersions< | ||
S extends Strategy.Specification | ||
> = S["allowsListingVersions"]; | ||
|
||
} | ||
|
||
/** | ||
* An object of type Strategy<S> provides version loading and possibly version | ||
* listing functionality | ||
*/ | ||
export type Strategy<S extends Strategy.Specification> = BaseStrategy<S> & | ||
(true extends Strategy.AllowsLoadingSpecificVersion<S> | ||
? { | ||
load(version?: string): Strategy.Results.Load<S>; | ||
} | ||
: { | ||
load(): Strategy.Results.Load<S>; | ||
}) & | ||
(true extends Strategy.AllowsListingVersions<S> | ||
? { | ||
list(): Strategy.Results.List<S>; | ||
} | ||
: {}); | ||
|
||
/** | ||
* An object of BaseStrategy<S> allows loading an unspecified version, plus | ||
* type guards to determine additional functionality | ||
*/ | ||
export interface BaseStrategy<S extends Strategy.Specification> { | ||
load(): Strategy.Results.Load<S>; | ||
|
||
allowsLoadingSpecificVersion(): this is this & { | ||
load(version?: string): Strategy.Results.Load<S>; | ||
}; | ||
|
||
allowsListingVersions(): this is { | ||
list(): Strategy.Results.List<S>; | ||
}; | ||
} |
Oops, something went wrong.