diff --git a/observable-slim.d.ts b/observable-slim.d.ts index e636606..82ecdfd 100644 --- a/observable-slim.d.ts +++ b/observable-slim.d.ts @@ -1,4 +1,35 @@ -export function create(target: any, domDelay: number | boolean, observer?: (arg0: { +// Type by StackOverflow user mindlid and 0x6368656174, modified by XDGFX +// https://stackoverflow.com/a/68404823/10843516 +type DotPrefix = T extends "" ? "" : `.${T}`; +type Paths = ( + T extends object + ? { + [K in Exclude]: `${K}${ + | DotPrefix> + | ""}`; + }[Exclude] + : "" +) extends infer D + ? Extract + : string; + +type PathToJSONPointer = S extends string + ? S extends `${infer T}.${infer U}` + ? `/${T}${PathToJSONPointer}` + : `/${S}` + : never; + +type Split = string extends S + ? string + : S extends `${infer T}${D}${infer U}` + ? U extends Split + ? T + : Split + : S; + +type LastSegment = S extends string ? Split : never; + +export interface Mutation> { /** * Change type. */ @@ -6,23 +37,23 @@ export function create(target: any, domDelay: number | boolean, observer?: (arg0 /** * Property name. */ - property: string; + property: LastSegment; /** * Property path with the dot notation (e.g. `foo.0.bar`). */ - currentPath: string; + currentPath: CurrentPath; /** * Property path with the JSON pointer syntax (e.g. `/foo/0/bar`). See https://datatracker.ietf.org/doc/html/rfc6901. */ - jsonPointer: string; + jsonPointer: PathToJSONPointer; /** * Target object. */ - target: any; + target: Source; /** * Proxy of the target object. */ - proxy: ProxyConstructor; + proxy: Source; /** * New value of the property. */ @@ -31,43 +62,19 @@ export function create(target: any, domDelay: number | boolean, observer?: (arg0 * Previous value of the property */ previousValue?: any; -}[]) => any): ProxyConstructor; -export function observe(proxy: ProxyConstructor, observer: (arg0: { - /** - * Change type. - */ - type: "add" | "update" | "delete"; - /** - * Property name. - */ - property: string; - /** - * Property path with the dot notation (e.g. `foo.0.bar`). - */ - currentPath: string; - /** - * Property path with the JSON pointer syntax (e.g. `/foo/0/bar`). See https://datatracker.ietf.org/doc/html/rfc6901. - */ - jsonPointer: string; - /** - * Target object. - */ - target: any; - /** - * Proxy of the target object. - */ - proxy: ProxyConstructor; - /** - * New value of the property. - */ - newValue: any; - /** - * Previous value of the property - */ - previousValue?: any; -}[]) => any): void; -export function pause(proxy: ProxyConstructor): void; -export function resume(proxy: ProxyConstructor): void; -export function pauseChanges(proxy: ProxyConstructor): void; -export function resumeChanges(proxy: ProxyConstructor): void; -export function remove(proxy: ProxyConstructor): void; +} + +export function create( + target: Source, + domDelay: number | boolean, + observer?: (mutations: Mutation[]) => void +): Source; +export function observe( + proxy: Source, + observer: (mutations: Mutation[]) => void +): void; +export function pause(proxy: Source): void; +export function resume(proxy: Source): void; +export function pauseChanges(proxy: Source): void; +export function resumeChanges(proxy: Source): void; +export function remove(proxy: Source): void; diff --git a/observable-slim.js b/observable-slim.js index b074768..f1b8e61 100644 --- a/observable-slim.js +++ b/observable-slim.js @@ -532,23 +532,24 @@ var ObservableSlim = (function() { * @property {string} property Property name. * @property {string} currentPath Property path with the dot notation (e.g. `foo.0.bar`). * @property {string} jsonPointer Property path with the JSON pointer syntax (e.g. `/foo/0/bar`). See https://datatracker.ietf.org/doc/html/rfc6901. - * @property {object} target Target object. - * @property {ProxyConstructor} proxy Proxy of the target object. - * @property {*} newValue New value of the property. - * @property {*} [previousValue] Previous value of the property + * @property {Source} target Target object. + * @property {Source} proxy Proxy of the target object. + * @property {Source} newValue New value of the property. + * @property {Source} [previousValue] Previous value of the property */ return { /** + * @template Source * Create a new ES6 `Proxy` whose changes we can observe through the `observe()` method. - * @param {object} target Plain object that we want to observe for changes. + * @param {Source} target Plain object that we want to observe for changes. * @param {boolean|number} domDelay If `true`, then the observed changes to `target` will be batched up on a 10ms delay (via `setTimeout()`). * If `false`, then the `observer` function will be immediately invoked after each individual change made to `target`. It is helpful to set * `domDelay` to `true` when your `observer` function makes DOM manipulations (fewer DOM redraws means better performance). If a number greater * than zero, then it defines the DOM delay in milliseconds. - * @param {function(ObservableSlimChange[])} [observer] Function that will be invoked when a change is made to the proxy of `target`. + * @param {(mutations: ObservableSlimChange[]) => void} [observer] Function that will be invoked when a change is made to the proxy of `target`. * When invoked, this function is passed a single argument: an array of `ObservableSlimChange` detailing each change that has been made. - * @returns {ProxyConstructor} Proxy of the target object. + * @returns {Source} Proxy of the target object. */ create: function(target, domDelay, observer) { @@ -583,9 +584,10 @@ var ObservableSlim = (function() { }, /** + * @template Source * Add a new observer function to an existing proxy. - * @param {ProxyConstructor} proxy An ES6 `Proxy` created by the `create()` method. - * @param {function(ObservableSlimChange[])} observer Function that will be invoked when a change is made to the proxy of `target`. + * @param {Source} proxy An ES6 `Proxy` created by the `create()` method. + * @param {(mutations: ObservableSlimChange[]) => void} observer Function that will be invoked when a change is made to the proxy of `target`. * When invoked, this function is passed a single argument: an array of `ObservableSlimChange` detailing each change that has been made. * @returns {void} Does not return any value. */ @@ -601,8 +603,9 @@ var ObservableSlim = (function() { }, /** + * @template Source * Prevent any observer functions from being invoked when a change occurs to a proxy. - * @param {ProxyConstructor} proxy An ES6 `Proxy` created by the `create()` method. + * @param {Source} proxy An ES6 `Proxy` created by the `create()` method. * @returns {void} Does not return any value. */ pause: function(proxy) { @@ -620,8 +623,9 @@ var ObservableSlim = (function() { }, /** + * @template Source * Resume execution of any observer functions when a change is made to a proxy. - * @param {ProxyConstructor} proxy An ES6 `Proxy` created by the `create()` method. + * @param {Source} proxy An ES6 `Proxy` created by the `create()` method. * @returns {void} Does not return any value. */ resume: function(proxy) { @@ -639,10 +643,11 @@ var ObservableSlim = (function() { }, /** + * @template Source * Prevent any changes (i.e., `set`, and `deleteProperty`) from being written to the target object. * However, the observer functions will still be invoked to let you know what changes **WOULD** have been made. * This can be useful if the changes need to be approved by an external source before the changes take effect. - * @param {ProxyConstructor} proxy An ES6 `Proxy` created by the `create()` method. + * @param {Source} proxy An ES6 `Proxy` created by the `create()` method. * @returns {void} Does not return any value. */ pauseChanges: function(proxy){ @@ -660,8 +665,9 @@ var ObservableSlim = (function() { }, /** + * @template Source * Resume the changes that were taking place prior to the call to `pauseChanges()` method. - * @param {ProxyConstructor} proxy An ES6 `Proxy` created by the `create()` method. + * @param {Source} proxy An ES6 `Proxy` created by the `create()` method. * @returns {void} Does not return any value. */ resumeChanges: function(proxy){ @@ -679,8 +685,9 @@ var ObservableSlim = (function() { }, /** + * @template Source * Remove the observable and proxy thereby preventing any further callback observers for changes occurring to the target object. - * @param {ProxyConstructor} proxy An ES6 `Proxy` created by the `create()` method. + * @param {Source} proxy An ES6 `Proxy` created by the `create()` method. * @returns {void} Does not return any value. */ remove: function(proxy) { diff --git a/package-lock.json b/package-lock.json index ab68a07..609dfca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "observable-slim", - "version": "0.1.5", + "version": "0.1.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "observable-slim", - "version": "0.1.5", + "version": "0.1.6", "license": "MIT", "devDependencies": { "@babel/core": "^7.17.8", diff --git a/package.json b/package.json index 87b19d4..fa4bb85 100644 --- a/package.json +++ b/package.json @@ -25,8 +25,7 @@ "lint": "eslint \"**/*.js\"", "lint:fix": "eslint \"**/*.js\" --fix", "coverage": "nyc report --reporter=text-lcov | coveralls", - "build": "gulp", - "type": "npx -p typescript tsc" + "build": "gulp" }, "babel": { "presets": [