Skip to content

Instantly share code, notes, and snippets.

@OliverJAsh
Last active September 25, 2018 07:35
Show Gist options
  • Save OliverJAsh/86f42335d1bbe6a7198b300f15eb3f22 to your computer and use it in GitHub Desktop.
Save OliverJAsh/86f42335d1bbe6a7198b300f15eb3f22 to your computer and use it in GitHub Desktop.
TypeScript higher-order function for applying defaults to function with named parameters
import { Diff } from 'typelevel-ts';
// Higher-order function
const withDefaultsFn = <DefaultParams extends object, Params extends DefaultParams, Result>(
fn: (params: Params) => Result,
defaultParams: DefaultParams,
) => (inputParams: Diff<Params, keyof DefaultParams>): Result =>
fn({
// We cast spreaded objects to any to workaround TS issue when spreading generic objects
// https://github.com/Microsoft/TypeScript/issues/14409
...(defaultParams as any),
...(inputParams as any),
});
function functionWithDefaultParams(a: string, b: number = 1) {}
functionWithDefaultParams('foo'); // defaults may be emitted
functionWithDefaultParams(); // non-defaults are required
functionWithDefaultParams(1); // non-defaults are type checked
functionWithDefaultParams('foo', 2); // defaults may be overridden
type Params = { a: string; b: number };
const defaults = {
b: 1,
};
function functionWithParamsNamed(params: Params) {}
const functionWithDefaultParamsNamed = withDefaultsFn(functionWithParamsNamed, defaults);
functionWithDefaultParamsNamed({ a: 'foo' }); // defaults may be emitted
functionWithDefaultParamsNamed({}); // non-defaults are required
functionWithDefaultParamsNamed({ a: 1 }); // non-defaults are type checked
functionWithDefaultParamsNamed({ a: 'foo', b: 2 }); // defaults may be overridden
{
"name": "with-defaults",
"private": true,
"scripts": {
"lint": "tslint --project ./tsconfig.json",
"compile": "tsc",
"start": "npm run compile && npm run lint && node ./target/index.js",
"format": "prettier --write './**/*.{ts,js,json}'"
},
"dependencies": {
"typelevel-ts": "^0.3.1"
},
"devDependencies": {
"prettier": "^1.13.5",
"tslint": "^5.10.0",
"tslint-language-service": "^0.9.9",
"typescript": "^3.0.3"
}
}
{
"compilerOptions": {
"module": "commonjs",
"target": "es2015",
"strict": true,
"noImplicitReturns": true,
"sourceMap": true,
"outDir": "./target/",
"rootDir": "./src/"
},
"files": ["./index.ts"]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment