Created
April 21, 2018 06:08
-
-
Save niieani/79cd42f80bd906540d2a31eab4bd58b5 to your computer and use it in GitHub Desktop.
TypeScript hacks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type HasProperty<X, P> = (X[keyof X & P] extends P ? true : false) extends false ? true : false | |
type example = HasProperty<{type:1}, 'type'> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
combineReducers, createStore, | |
Action | |
} from 'redux' | |
type SiteState = {something: string} | |
const LOAD = 'LOAD' | |
const siteActions = { | |
[LOAD]: (state : SiteState | undefined, action : {type: typeof LOAD, baba: string}): SiteState => ({ | |
...state!, | |
}), | |
['THING']: (state : SiteState | undefined, action : {type: 'THING', a: number}): SiteState => ({ | |
...state!, | |
}) | |
} | |
type StateFromReducersObject<T extends { | |
[type : string] : <S>(state : S | undefined, action : any) => S | |
}, Types extends keyof T = keyof T> = T extends { | |
[type : string] : (state : infer State | undefined, action : any) => infer State | |
} ? State : never | |
type BaseReducer<Type extends string> = | |
<State extends {}>(state : State | undefined, action : Action<Type>) => State; | |
type Reducer<Type extends string, Reducer extends (state : any, action : Action<Type>) => any = any> = | |
// type Reducer<Type extends string = '', Reducer extends Function = any> = | |
Reducer extends <State extends {}>(state : State | undefined, action : infer A) => State | |
? Reducer //& BaseReducer<Type> | |
: never; //BaseReducer<Type>; | |
type ActionFromReducer<Reducer extends (state : any, action : Action) => any = any> = | |
// type ActionFromReducer<Reducer extends Function = any> = | |
// Reducer extends (state: any, action: infer A) => any ? EnsureAction<A> : never; | |
Reducer extends (state: any, action: infer A) => any ? EnsureAction<A> : never; | |
type EnsureAction<A> = A //& {type: A[keyof A & 'type']} | |
const createReducer = ( | |
< | |
Reducers extends {[Type in Types] : Reducer<Type>}, //& {[type: string]: Reducer<Type>}, | |
Types extends keyof Reducers, | |
State = StateFromReducersObject<Reducers>, | |
MergedActions = ActionsFromReducers<Reducers>[keyof ActionsFromReducers<Reducers>], | |
// MergedActions extends Action = ActionFromReducer<Reducers[Types]>, | |
>(reducers : Reducers) => | |
(state: State, action: MergedActions): State => | |
(reducers as any)[(action as any).type](state, action) | |
// <Type extends keyof Reducers>(state: State, action: ActionFromReducer<Reducers[Type]>): State => | |
// reducers[action.type](state, action) | |
) | |
const site = createReducer(siteActions); | |
site({something: 'abc'}, {type: "LOAD", baba: 'abc'}) | |
// type Dupa = ActionFromReducer<typeof site> | |
// export type ReducersMapObject< | |
// Reducers extends {[Type in Types] : Reducer<Type>}, | |
// Types extends keyof Reducers, | |
// A extends Action = Action | |
// > = { | |
// [K in keyof Reducers]: Reducer<A['type'], Reducers[K]>; | |
// } | |
// type MergeReducers = < | |
// Reducers extends { [Type in Types]: any; }, | |
// Types extends keyof Reducers, | |
// State = Reducers extends { | |
// [type: string]: (state: infer State | undefined, action: any) => infer State; | |
// } ? State : never | |
// >(reducers: Reducers) => | |
// <Type extends keyof Reducers>( | |
// state: State, | |
// action: (Reducers[Type] extends (state: any, action: infer Action) => any ? Action : never) & Action<Type> | |
// ) => State | |
type CombineReducers = < | |
Map extends {[Prefix in Prefixes]: (state: any, action: any) => any}, | |
Prefixes extends keyof Map, | |
MergedState = { | |
readonly [Prefix in Prefixes]: ReturnType<Map[Prefix]> | |
}, | |
MergedActions = MergedActionsFromReducers<Map>, | |
>(map: Map) => | |
(state: MergedState | undefined, action: MergedActions) => MergedState | |
type GenericReducerMap<Map> = {[Prefix in keyof Map]: (state: any, action: any) => any} | |
type ActionsFromReducers<Map extends GenericReducerMap<Map>> = { | |
[Prefix in keyof Map]: ActionFromReducer<Map[Prefix]> | |
} | |
type MergedActionsFromReducers<Map extends GenericReducerMap<Map>> = ActionsFromReducers<Map>[keyof ActionsFromReducers<Map>] | |
declare var combine : CombineReducers | |
const toCombine = { | |
site | |
} | |
const reducer = combine(toCombine) | |
reducer({site: {something: 'hi'}}, {type: 'LOAD', baba: '123', x: 1}) | |
// combineReducers | |
// export const store = createStore(reducer) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment