Skip to content

Commit

Permalink
fix types
Browse files Browse the repository at this point in the history
  • Loading branch information
megazazik committed Apr 11, 2020
1 parent b6cbc7d commit 4bf9bed
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 82 deletions.
108 changes: 45 additions & 63 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,10 @@ export abstract class Assistant<S> {

private readonly assistants = new Set<Assistant<any>>();

protected createAssistant<
AssistantS = S,
A extends Assistant<AssistantS> = Assistant<AssistantS>
>(config: AssistantConfig<S, AssistantS, A>) {
const newAssistant = createAssistant(
protected createAssistant<A extends Assistant<any>>(
config: AssistantConfig<A, S>
) {
const newAssistant: A = createAssistant(
config,
() => this.state,
this[dispatchSymbol],
Expand All @@ -154,34 +153,32 @@ export abstract class Assistant<S> {
}
}

export type Configs<S> = Array<AssistantConfig<S, any, any>>;
export type Configs<S> = Array<AssistantConfig<Assistant<any>, S>>;

export function addSelect<
K extends string,
S,
AssistantS = S,
A extends Assistant<AssistantS> = Assistant<AssistantS>
A extends Assistant<any>,
S = StateOfAssistant<A>
>(
select: K,
config: AssistantConfig<S, AssistantS, A>
): AssistantConfig<{ [P in K]: S }, AssistantS, A>;
config: AssistantConfig<A, S>
): AssistantConfig<A, { [P in K]: S }>;
export function addSelect<
NewS,
S,
AssistantS = S,
A extends Assistant<AssistantS> = Assistant<AssistantS>
A extends Assistant<any>,
S = StateOfAssistant<A>
>(
select: (s: NewS) => S,
config: AssistantConfig<S, AssistantS, A>
): AssistantConfig<NewS, AssistantS, A>;
export function addSelect<NewS, K extends keyof NewS>(
config: AssistantConfig<A, S>
): AssistantConfig<A, NewS>;
export function addSelect<K extends string, S>(
select: K,
configs: Array<AssistantConfig<NewS[K], any, any>>
): AssistantConfig<NewS, any, any>;
configs: Configs<S>
): Configs<{ [P in K]: S }>;
export function addSelect<NewS, S>(
select: (s: NewS) => S,
configs: Array<AssistantConfig<S, any, any>>
): AssistantConfig<NewS, any, any>;
configs: Configs<S>
): Configs<NewS>;
export function addSelect(
select: string | ((s: any) => any),
config: AssistantConfig<any> | Array<AssistantConfig<any>>
Expand All @@ -205,40 +202,37 @@ function innerAddSelect(
};
}

type StateOfAssistant<A extends Assistant<any>> = A extends Assistant<infer S>
? S
: never;

export type AssistantConfig<
S,
AssistantS = S,
A extends Assistant<AssistantS> = Assistant<AssistantS>
A extends Assistant<any>,
S = StateOfAssistant<A>
> =
| { new (): A }
| ConstructorAssistantConfig<S, AssistantS, A>
| CreateAssistantConfig<S, AssistantS, A>;
| ConstructorAssistantConfig<A, S>
| CreateAssistantConfig<A, S>;

type ConstructorAssistantConfig<
S,
AssistantS = S,
A extends Assistant<AssistantS> = Assistant<AssistantS>
A extends Assistant<any>,
S = StateOfAssistant<A>
> = {
Constructor: { new (): A };
select: (s: S) => AssistantS;
select: (s: S) => StateOfAssistant<A>;
};

type CreateAssistantConfig<
S,
AssistantS = S,
A extends Assistant<AssistantS> = Assistant<AssistantS>
A extends Assistant<any>,
S = StateOfAssistant<A>
> = {
create(): A;
select: (s: S) => AssistantS;
create: () => A;
select: (s: S) => StateOfAssistant<A>;
};

function getCreateConfig<
S,
AssistantS = S,
A extends Assistant<AssistantS> = Assistant<AssistantS>
>(
config: AssistantConfig<S, AssistantS, A>
): CreateAssistantConfig<S, AssistantS, A> {
function getCreateConfig<A extends Assistant<any>, S>(
config: AssistantConfig<A, S>
): CreateAssistantConfig<A, S> {
if (typeof config === 'function') {
return {
select: (s) => s as any,
Expand All @@ -260,34 +254,26 @@ function getCreateConfig<
throw new Error('Incorrect assistant config');
}

function isConstructorConfig<
S,
AssistantS = S,
A extends Assistant<AssistantS> = Assistant<AssistantS>
>(
config: AssistantConfig<S, AssistantS, A>
): config is ConstructorAssistantConfig<S, AssistantS, A> {
function isConstructorConfig<A extends Assistant<any>, S>(
config: AssistantConfig<A, S>
): config is ConstructorAssistantConfig<A, S> {
return (
typeof config === 'object' &&
typeof (config as any).Constructor === 'function'
);
}

function isCreateConfig<
S,
AssistantS = S,
A extends Assistant<AssistantS> = Assistant<AssistantS>
>(
config: AssistantConfig<S, AssistantS, A>
): config is ConstructorAssistantConfig<S, AssistantS, A> {
function isCreateConfig<A extends Assistant<any>, S>(
config: AssistantConfig<A, S>
): config is ConstructorAssistantConfig<A, S> {
return (
typeof config === 'object' &&
typeof (config as any).create === 'function'
);
}

export const enhancer: <S>(
assistantConfigs: Array<AssistantConfig<S, any, any>>
assistantConfigs: Array<AssistantConfig<any, S>>
) => StoreEnhancer = (assistantConfigs) => (createStore) => {
const newCreateStore: StoreEnhancerStoreCreator<{}, {}> = (
reducer,
Expand Down Expand Up @@ -319,12 +305,8 @@ export const enhancer: <S>(
return newCreateStore;
};

function createAssistant<
S,
AssistantS = S,
A extends Assistant<AssistantS> = Assistant<AssistantS>
>(
config: AssistantConfig<S, AssistantS, A>,
function createAssistant<A extends Assistant<any>, S>(
config: AssistantConfig<A, S>,
getState: () => S,
dispatch: (action: any) => void,
subscribe: (callback: () => void) => Unsubscribe,
Expand Down
10 changes: 6 additions & 4 deletions src/tmp/assistant.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { model } from './model';
import { Assistant } from '..';
import { Assistant, addSelect } from '..';

export class ModelAssistant extends Assistant<typeof model> {
export class ModelAssistant extends Assistant<
ReturnType<typeof model.reducer>
> {
private tmp: Temp;

onInit() {
this.afterAction('mytest', () => {
// this.dispatch({ type: 'model3.model1.setValue', payload: 876 });
this.tmp = this.createAssistant(() => new Temp());
this.tmp = this.createAssistant(addSelect('model3', Temp));
});

this.afterAction('remove', () => {
Expand All @@ -16,7 +18,7 @@ export class ModelAssistant extends Assistant<typeof model> {
}
}

class Temp extends Assistant<typeof model> {
class Temp extends Assistant<any> {
onInit() {
this.beforeAction((action) => {
console.log('before action', action);
Expand Down
20 changes: 11 additions & 9 deletions src/tmp/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import { createStore } from 'redux';
import { createModule, enhancer } from '..';
import module3 from './module3';
import { enhancer, addSelect } from '..';
import { assistants } from './module3';
import { model } from './model';
import { ModelAssistant } from './assistant';

const module = createModule({
model: model,
children: [module3],
effects: [ModelAssistant],
});

console.log('start');

const store = createStore(module.model.reducer, enhancer(module));
addSelect('model3', assistants);

const store = createStore(
model.reducer,
enhancer<ReturnType<typeof model.reducer>>([
ModelAssistant,
...addSelect('model3', assistants),
])
);

console.log('state', store.getState());

Expand Down
7 changes: 1 addition & 6 deletions src/tmp/module3/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,5 @@ export { model3 };
export const assistants: Configs<State3> = [
Model3Assistant,
addSelect('model2', Model2Assistant),
addSelect('model2', Model1Assistant),
addSelect('model1', Model1Assistant),
];

const t = addSelect('model2', {
Constructor: Model1Assistant,
select: ({ model2 }) => model2,
});

0 comments on commit 4bf9bed

Please sign in to comment.