Skip to content

Commit a05dad6

Browse files
authored
feat(typescript): Inherit options types set in Base.defaults() (#33) thanks @jacobwgillespie
1 parent 3e64163 commit a05dad6

File tree

3 files changed

+37
-9
lines changed

3 files changed

+37
-9
lines changed

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
"types": "./index.d.ts",
77
"scripts": {
88
"build": "tsc src/index.ts --declaration --outDir .",
9-
"test": "jest --coverage"
9+
"test": "npm run -s test:code && npm run -s test:typescript",
10+
"test:code": "jest --coverage",
11+
"test:typescript": "npx tsc --noEmit --declaration --noUnusedLocals test-typescript.ts"
1012
},
1113
"repository": "github:gr2m/javascript-plugin-architecture-with-typescript-definitions",
1214
"keywords": [

src/index.ts

+12-8
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ type ReturnTypeOf<T extends AnyFunction | AnyFunction[]> = T extends AnyFunction
2727
? UnionToIntersection<ReturnType<T[number]>>
2828
: never;
2929

30-
export class Base {
30+
export class Base<TOptions extends Options = Options> {
3131
static plugins: TestPlugin[] = [];
3232
static plugin<
3333
S extends Constructor<any> & { plugins: any[] },
@@ -46,21 +46,25 @@ export class Base {
4646
);
4747
};
4848

49-
return BaseWithPlugins as typeof this & { plugins: any[] } &
50-
Constructor<UnionToIntersection<ReturnTypeOf<T1> & ReturnTypeOf<T2>>>;
49+
return BaseWithPlugins as typeof this & { plugins: any[] } & Constructor<
50+
UnionToIntersection<ReturnTypeOf<T1> & ReturnTypeOf<T2>>
51+
>;
5152
}
5253

53-
static defaults<S extends Constructor<any>>(this: S, defaults: Options) {
54+
static defaults<
55+
TDefaults extends Options,
56+
S extends Constructor<Base<TDefaults>>
57+
>(this: S, defaults: TDefaults) {
5458
const BaseWitDefaults = class extends this {
5559
constructor(...args: any[]) {
5660
super(Object.assign({}, defaults, args[0] || {}));
5761
}
5862
};
5963

60-
return BaseWitDefaults as typeof this;
64+
return BaseWitDefaults as typeof BaseWitDefaults & typeof this;
6165
}
6266

63-
constructor(options: Options = {}) {
67+
constructor(options: TOptions = {} as TOptions) {
6468
this.options = options;
6569

6670
// apply plugins
@@ -71,5 +75,5 @@ export class Base {
7175
});
7276
}
7377

74-
options: Options;
75-
}
78+
options: TOptions;
79+
}

test-typescript.ts

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// ************************************************************
2+
// THIS CODE IS NOT EXECUTED. IT IS JUST FOR TYPECHECKING
3+
// ************************************************************
4+
5+
import { Base } from "./src";
6+
7+
function isString(what: string) {}
8+
9+
// sets .options types from constructor options
10+
const base = new Base({ option: "value" });
11+
isString(base.options.option);
12+
13+
// sets .options types from Base.defaults({})
14+
const BaseWithDefaults = Base.defaults({ parentOption: "value" });
15+
const baseWithDefaults = new BaseWithDefaults({ childOption: "value" });
16+
17+
isString(baseWithDefaults.options.childOption);
18+
// see #32
19+
isString(baseWithDefaults.options.parentOption);
20+
21+
// @ts-expect-error see #31
22+
baseWithDefaults.unknown;

0 commit comments

Comments
 (0)