From f02e9ae4ddf6d14ea79f8aea32c7182dce82cb3b Mon Sep 17 00:00:00 2001 From: Martin Hochel Date: Tue, 12 Jun 2018 13:57:32 +0200 Subject: [PATCH] [webpack-config-utils]: add type definitions --- types/webpack-config-utils/index.d.ts | 64 +++++++++++ types/webpack-config-utils/tsconfig.json | 23 ++++ types/webpack-config-utils/tslint.json | 1 + .../webpack-config-utils-tests.ts | 101 ++++++++++++++++++ 4 files changed, 189 insertions(+) create mode 100644 types/webpack-config-utils/index.d.ts create mode 100644 types/webpack-config-utils/tsconfig.json create mode 100644 types/webpack-config-utils/tslint.json create mode 100644 types/webpack-config-utils/webpack-config-utils-tests.ts diff --git a/types/webpack-config-utils/index.d.ts b/types/webpack-config-utils/index.d.ts new file mode 100644 index 0000000000..829f88296e --- /dev/null +++ b/types/webpack-config-utils/index.d.ts @@ -0,0 +1,64 @@ +// Type definitions for webpack-config-utils 2.3 +// Project: https://github.com/kentcdodds/webpack-config-utils#readme +// Definitions by: Martin Hochel +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.8 + +/*~ You can declare properties of the module using const, let, or var */ +// declare const getIfUtils: WebpackConfigUtils.GetIfUtils; +// declare const removeEmpty: WebpackConfigUtils.RemoveEmpty; +// declare const propIf: WebpackConfigUtils.PropIf; +// declare const propIfNot: WebpackConfigUtils.PropIfNot; + +declare const api: WebpackConfigUtils.API; +export = api; + +declare namespace WebpackConfigUtils { + type Falsy = false | '' | undefined | null | 0; + type DefinedObjKeys = ({ [P in keyof T]: T[P] extends undefined ? never : P })[keyof T]; + type NonEmptyObject = DefinedObjKeys> = { [PP in P]: T[PP] }; + + type EnvVars = 'production' | 'prod' | 'test' | 'development' | 'dev'; + interface RemoveEmpty { + (input: Array): T[]; + (input: { [P in keyof T]: T[P] }): NonEmptyObject; + } + type GetIfUtils = ( + env: { [P in E]: boolean | string } | E, + vars?: Array + ) => IfUtils; + // @TODO + // with following defintion, generics will get flattened to base type -> string. Any ideas why or how to fix this? + // $ExpectType "value" | "alternate" + // propIf(true, 'value', 'alternate'); // 'value' + // + // type PropIf = (add: A, value: I, alternate: E) => A extends Falsy ? E : I; + // type PropIfNot = (add: A, value: I, alternate: E) => A extends Falsy ? I : E; + type PropIf = (add: any, value: I, alternate: E) => I | E; + type PropIfNot = PropIf; + + interface IfUtilsFn { + (value: Y, alternate?: N): Y | N; + (): boolean; + } + interface IfUtils { + ifDevelopment: IfUtilsFn; + ifNotDevelopment: IfUtilsFn; + ifDev: IfUtilsFn; + ifNotDev: IfUtilsFn; + ifProduction: IfUtilsFn; + ifNotProduction: IfUtilsFn; + ifProd: IfUtilsFn; + ifNotProd: IfUtilsFn; + ifTest: IfUtilsFn; + ifNotTest: IfUtilsFn; + [key: string]: IfUtilsFn; + } + + interface API { + getIfUtils: GetIfUtils; + removeEmpty: RemoveEmpty; + propIf: PropIf; + propIfNot: PropIfNot; + } +} diff --git a/types/webpack-config-utils/tsconfig.json b/types/webpack-config-utils/tsconfig.json new file mode 100644 index 0000000000..0376cbd868 --- /dev/null +++ b/types/webpack-config-utils/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "webpack-config-utils-tests.ts" + ] +} diff --git a/types/webpack-config-utils/tslint.json b/types/webpack-config-utils/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/webpack-config-utils/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" } diff --git a/types/webpack-config-utils/webpack-config-utils-tests.ts b/types/webpack-config-utils/webpack-config-utils-tests.ts new file mode 100644 index 0000000000..a8ca450b20 --- /dev/null +++ b/types/webpack-config-utils/webpack-config-utils-tests.ts @@ -0,0 +1,101 @@ +import webpackConfigUtils = require('webpack-config-utils'); +import { getIfUtils, removeEmpty, propIf, propIfNot } from 'webpack-config-utils'; + +{ + // propIf/propIfNot + + // $ExpectType "value" | "alternate" + propIf(true, 'value', 'alternate'); // 'value' + + // $ExpectType "value" | "alternate" + propIf(false, 'value', 'alternate'); // 'alternate' + + // $ExpectType "value" | "alternate" + propIf('false', 'value', 'alternate'); // 'alternate' + + // $ExpectType "value" | "alternate" + propIfNot(true, 'value', 'alternate'); // 'alternate' + + // $ExpectType "value" | "alternate" + propIfNot(false, 'value', 'alternate'); // 'value' + + // $ExpectType "value" | "alternate" + propIfNot('false', 'value', 'alternate'); // 'value' +} +{ + // getIfUtils + { + const expectedMethods = [ + 'ifProduction', + 'ifNotProduction', + 'ifProd', + 'ifNotProd', + 'ifTest', + 'ifNotTest', + 'ifDevelopment', + 'ifNotDevelopment', + 'ifDev', + 'ifNotDev' + ]; + const utils = getIfUtils({}); + } + { + const expectedMethods = ['ifFoo', 'ifNotFoo', 'ifBar', 'ifNotBar']; + const utils = getIfUtils({}, ['foo', 'bar']); + const { ifFoo, ifBar, ifNotFoo, ifNotBar } = utils; + } + + { + const { ifProduction } = getIfUtils('production'); + + // $ExpectType "value" | "alternate" + ifProduction('value', 'alternate'); // 'value' + } + { + const { ifNotDev } = getIfUtils({ dev: false }); + + // $ExpectType "value" | "alternate" + ifNotDev('value', 'alternate'); // 'value' + } + { + // $ExpectError + getIfUtils(false); // webpack-config-utils:getIfUtils.*?string\/Object/); + } + { + const { ifTest, ifProd, ifNotDev } = getIfUtils('test'); + // $ExpectType boolean + ifTest(); // true; + // $ExpectType boolean + ifProd(); // false; + // $ExpectType boolean + ifNotDev(); // true; + } + { + const { ifWatch, ifProd, ifNotDev, ifTest } = getIfUtils('watch', ['prod', 'dev', 'watch']); + // $ExpectType boolean + ifWatch(); // true + // $ExpectType boolean + ifProd(); // false + // $ExpectType boolean + ifNotDev(); // true + // $ExpectType IfUtilsFn + ifTest; // function + } +} +{ + // removeEmpty + // $ExpectType (number | null)[] + const emptiedArray = removeEmpty([undefined, 0, 1, 2, undefined, 3, undefined, null]); // [0, 1, 2, 3, null] + + // $ExpectType NonEmptyObject<{ a: number; b: string; c: undefined; d: null; }, "b" | "a" | "d"> + const emptiedObject = removeEmpty({ a: 1, b: 'b', c: undefined, d: null }); // {a: 1, b: 'b', d: null} + const {a, b, d} = emptiedObject; + + { + // $ExpectError + const {a, b, c, d} = emptiedObject; // Error + } + + // $ExpectType number | null + const firstItem = emptiedArray[0]; +}