import { generateId , memorize } from "./helper" ; author cluezhang
  type GLOBAL_SELECTOR < T > = T extends ( state : any , ... rest : infer U ) => infer K ? ( globalState : any , ... rest : U ) => K : never ; type GLOBAL_SELECTORS < T > = { [ key in keyof T ] : GLOBAL_SELECTOR < T [ key ] > ; } ; export type DuckState < T extends BaseDuck > = ReturnType < T [ "reducer" ] > ; export interface DuckOptions { namespace : string ; selector ( globalState ) : any ; route : string ; } function getDefaultDuckOptions ( ) { return { namespace : Math . random ( ) . toString ( 36 ) . slice ( 2 , 10 ) , selector ( a ) { return a ; } , route : "" } ; } export type TYPES < T > = { readonly [ P in keyof T ] : string ; } ; /**
 * 支持reducer的Duck
 *
 * Duck support reducer(not reducers)
 */ export default abstract class BaseDuck { protected id : string = generateId ( ) ; constructor ( protected options = getDefaultDuckOptions ( ) ) { this . _checkDisallowInheritGetters ( ) ; this . _makeCacheGetters ( ) ; } protected get _disallowInheritGetters ( ) { return [ "types" , "selectors" , "selector" ] ; } private _checkDisallowInheritGetters ( ) { for ( const property of this . _disallowInheritGetters ) { let target = this ; let count = 0 ; while ( target ) { target = Object . getPrototypeOf ( target ) ; if ( ! target ) { break ; } const descriptor = Object . getOwnPropertyDescriptor ( target , property ) ; if ( descriptor ) { count ++ ; } if ( count > 1 ) { throw new Error ( `Getter ${ property }() disallow inherit` ) ; } } } } /** 内部属性，ActionType前缀 Internal property, prefix of action type. */ protected get actionTypePrefix ( ) : string { const { namespace , route } = this . options ; return route ? `${ namespace }/${ route }/` : `${ namespace }/` ; } protected get _cacheGetters ( ) { return [ "types" , "rawSelectors" , "selectors" , "creators" ] ; } private _makeCacheGetters ( ) { const me = this ; for ( const property of this . _cacheGetters ) { let descriptor = null ; let target = this ; while ( ! descriptor ) { target = Object . getPrototypeOf ( target ) ; if ( ! target ) { break ; } descriptor = Object . getOwnPropertyDescriptor ( target , property ) ; } if ( ! descriptor ) { continue ; } let cache ; Object . defineProperty ( this , property , { get ( ) { if ( ! cache ) { cache = descriptor . get . call ( me ) ; } return cache ; } } ) ; } } example get types ( ) : TYPES < this [ "quickTypes" ] > & this [ "rawTypes" ] { return Object . assign ( { } , this . makeTypes < this [ "quickTypes" ] > ( this . quickTypes ) , this . rawTypes ) ; } example get quickTypes ( ) { return { } ; } example get rawTypes ( ) { return { } ; } example param typeEnum protected makeTypes < T > ( typeEnum ) { const prefix = this . actionTypePrefix ; let typeList = [ ] ; const types = { } as TYPES < T > ; if ( typeEnum ) { typeList = typeList . concat ( Object . keys ( typeEnum ) ) ; } typeList . forEach ( ( type ) => { types [ type as string ] = prefix + type ; } ) ; return types ; } /** Reducer定义 reducer define*/ abstract get reducer ( ) ; example get State ( ) : DuckState < this > { throw new Error ( "State() Only use for get state type in Typescript, should not be invoke" ) ; } example get selector ( ) : ( globalState : any ) => this [ "State" ] { return this . options . selector ; } example get selectors ( ) : GLOBAL_SELECTORS < this [ "rawSelectors" ] > { const { selector , rawSelectors } = this ; const selectors = { } as GLOBAL_SELECTORS < this [ "rawSelectors" ] > ; for ( const key of Object . keys ( rawSelectors ) ) { selectors [ key ] = ( globalState , ... rest ) => rawSelectors [ key ] ( selector ( globalState ) , ... rest ) ; } return selectors ; } example get rawSelectors ( ) { return { } ; } /** 历史兼容  */ get localSelectors ( ) : this [ "rawSelectors" ] { return this . rawSelectors ; } example get creators ( ) { return { } ; } example * saga ( ) { } /** 历史兼容 */ get sagas ( ) { return [ this . saga . bind ( this ) ] ; } static memorize = memorize ; }