Skip to content

Commit

Permalink
Type tree-select
Browse files Browse the repository at this point in the history
  • Loading branch information
sirreal committed Jan 4, 2021
1 parent 6e064ff commit 7230688
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 24 deletions.
13 changes: 9 additions & 4 deletions packages/tree-select/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"license": "GPL-2.0-or-later",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"calypso:src": "src/index.js",
"calypso:src": "src/index.ts",
"sideEffects": false,
"repository": {
"type": "git",
Expand All @@ -28,9 +28,14 @@
"dist",
"src"
],
"types": "dist/types",
"scripts": {
"clean": "npx rimraf dist",
"build": "transpile",
"prepack": "yarn run clean && yarn run build"
"clean": "tsc --build ./tsconfig.json ./tsconfig-cjs.json --clean",
"build": "tsc --build ./tsconfig.json ./tsconfig-cjs.json",
"prepack": "yarn run clean && yarn run build",
"watch": "tsc --build ./tsconfig.json --watch"
},
"dependencies": {
"tslib": "^1.10.0"
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,56 @@
const defaultGetCacheKey = ( ...args ) => args.join();
declare const process: {
env: {
NODE_ENV: unknown;
};
};

interface GenerateCacheKey< A extends unknown[] > {
( ...args: A ): string;
}

const defaultGetCacheKey: GenerateCacheKey< unknown[] > = ( ...args: unknown[] ): string =>
args.join();

const isFunction = ( fn ) => {
const isFunction = ( fn: unknown ): fn is ( ...args: unknown[] ) => unknown => {
return fn && typeof fn === 'function';
};

const isObject = ( o ) => {
const isObject = ( o: unknown ): o is Record< string, unknown > => {
return o && typeof o === 'object';
};

type WeakMapKey = object; // eslint-disable-line @typescript-eslint/ban-types

interface Options< A extends unknown[] > {
/** Custom way to compute the cache key from the `args` list */
getCacheKey?: GenerateCacheKey< A >;
}

interface CachedSelector< S, A extends unknown[], R = unknown > {
( state: S, ...args: A ): R;
clearCache: () => void;
}

/**
* Returns a selector that caches values.
*
* @param {Function} getDependents A Function describing the dependent(s) of the selector.
* Must return an array which gets passed as the first arg to the selector
* @param {Function} selector A standard selector for calculating cached result
* @param {object} options Options bag with additional arguments
* @param {Function} options.getCacheKey
* Custom way to compute the cache key from the `args` list
* @returns {Function} Cached selector
* @param getDependents A Function describing the dependent(s) of the selector.
* Must return an array which gets passed as the first arg to the selector.
* @param selector A standard selector for calculating cached result.
* @param options Options bag with additional arguments.
*
* @returns {Function} Cached selector
*/
export default function treeSelect( getDependents, selector, options = {} ) {
export default function treeSelect<
State = unknown,
Args extends unknown[] = unknown[],
Deps extends WeakMapKey[] = any[], // eslint-disable-line @typescript-eslint/no-explicit-any
Result = unknown
>(
getDependents: ( state: State, ...args: Args ) => Deps,
selector: ( deps: Deps, ...args: Args ) => Result,
options: Options< Args > = {}
): CachedSelector< State, Args, Result > {
if ( process.env.NODE_ENV !== 'production' ) {
if ( ! isFunction( getDependents ) || ! isFunction( selector ) ) {
throw new TypeError(
Expand All @@ -32,7 +63,10 @@ export default function treeSelect( getDependents, selector, options = {} ) {

const { getCacheKey = defaultGetCacheKey } = options;

const cachedSelector = function ( state, ...args ) {
const cachedSelector: CachedSelector< State, Args, Result > = function (
state: State,
...args: Args
) {
const dependents = getDependents( state, ...args );

if ( process.env.NODE_ENV !== 'production' ) {
Expand All @@ -44,11 +78,11 @@ export default function treeSelect( getDependents, selector, options = {} ) {
// create a dependency tree for caching selector results.
// this is beneficial over standard memoization techniques so that we can
// garbage collect any values that are based on outdated dependents
const leafCache = dependents.reduce( insertDependentKey, cache );
const leafCache: Map< string, Result > = dependents.reduce( insertDependentKey, cache );

const key = getCacheKey( ...args );
if ( leafCache.has( key ) ) {
return leafCache.get( key );
return leafCache.get( key ) as Result;
}

const value = selector( dependents, ...args );
Expand Down Expand Up @@ -76,7 +110,8 @@ const NULLISH_KEY = {};
* Note: Inserts WeakMaps except for the last map which will be a regular Map.
* The last map is a regular one because the the key for the last map is the string results of args.join().
*/
function insertDependentKey( map, key, currentIndex, arr ) {
function insertDependentKey( map: any, key: unknown, currentIndex: number, arr: unknown[] ) {
// eslint-disable-line @typescript-eslint/no-explicit-any
if ( key != null && Object( key ) !== key ) {
throw new TypeError( 'key must be an object, `null`, or `undefined`' );
}
Expand Down
12 changes: 12 additions & 0 deletions packages/tree-select/tsconfig-cjs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"extends": "./tsconfig",
"compilerOptions": {
"module": "commonjs",
"declaration": false,
"declarationMap": false,
"declarationDir": null,
"outDir": "dist/cjs",
"composite": false,
"incremental": true
}
}
37 changes: 33 additions & 4 deletions packages/tree-select/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,36 @@
{
"extends": "@automattic/calypso-build/tsconfig",
"exclude": [ "node_modules" ],
"compilerOptions": {
"allowJs": true
}
"target": "ES5",
"lib": [ "ES2015" ],
"module": "ESNEXT",
"allowJs": false,
"declaration": true,
"declarationMap": true,
"declarationDir": "dist/types",
"rootDir": "src",
"outDir": "dist/esm",

"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,

"moduleResolution": "node",
"esModuleInterop": true,
"downlevelIteration": true,

"forceConsistentCasingInFileNames": true,

"importsNotUsedAsValues": "error",

"typeRoots": [ "../../node_modules/@types" ],
"types": [],

"noEmitHelpers": true,
"importHelpers": true,

"composite": true
},
"files": [ "src/index.ts" ]
}
3 changes: 2 additions & 1 deletion packages/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
{ "path": "./plans-grid" },
{ "path": "./react-i18n" },
{ "path": "./search" },
{ "path": "./shopping-cart" }
{ "path": "./shopping-cart" },
{ "path": "./tree-select" }
]
}

0 comments on commit 7230688

Please sign in to comment.