refactor: require types on method creator

This commit is contained in:
EnixCoda 2019-02-19 16:26:17 +08:00
parent f50af5c62d
commit 302d60b4a2
No known key found for this signature in database
GPG key ID: 6825847C88AA329A
3 changed files with 45 additions and 45 deletions

View file

@ -37,26 +37,26 @@ function run<M extends Method>([method, args]: [M, Parameters<M>]) {
method.apply(null, args)
}
export type DispatchState<Props> = React.Component<Props, void>['setState']
export type DispatchState<Props, State> = React.Component<Props, State>['setState']
export type PreDispatch<Props, State> = (
dispatchCallback: (props: Props, state: State) => Props | Promise<void> | void,
dispatchCallback: (state: State, props: Props) => Props | Promise<void> | void,
callback?: () => void
) => void
export type TriggerOtherMethod = <MC extends MethodCreator>(
export type TriggerOtherMethod = <MC extends MethodCreator<any, any>>(
methodCreator: MC,
...args: ParametersOfReturnedFunction<MC>
) => void
export type Dispatch<Props, State> = {
set: DispatchState<Props>
set: DispatchState<Props, State>
get: PreDispatch<Props, State>
call: TriggerOtherMethod
}
export type MethodCreator<Props = {}, State = any> = (dispatch: Dispatch<Props, State>) => Method
export type MethodCreator<Props, State> = (dispatch: Dispatch<Props, State>) => Method
type Sources = {
[key: string]: MethodCreator
[key: string]: MethodCreator<any, any>
}
type WrappedMethods = {
[key: string]: Method
@ -66,7 +66,7 @@ function link<P, S>(instance: React.Component<P, S>, sources: Sources): WrappedM
const wrappedMethods: WrappedMethods = {
/* [keyof sources] -> wrappedMethods.method */
}
const map = new Map<MethodCreator, Method>(/* sources.creator -> wrappedMethods.method */)
const map = new Map<MethodCreator<P, S>, Method>(/* sources.creator -> wrappedMethods.method */)
const dispatchCall: TriggerOtherMethod = (createMethod, ...otherArgs) => {
const isFromSource = sourcesValues.includes(createMethod)
@ -76,11 +76,11 @@ function link<P, S>(instance: React.Component<P, S>, sources: Sources): WrappedM
run(runnable)
}
}
const dispatchState: DispatchState<P> = (updater, callback) => {
const dispatchState: DispatchState<P, S> = (updater, callback) => {
instance.setState(updater, callback)
}
const prepareState: PreDispatch<P, S> = updater => {
updater(instance.props, instance.state)
updater(instance.state, instance.props)
}
const dispatch: Dispatch<P, S> = {
call: dispatchCall,

View file

@ -39,7 +39,7 @@ type Task = () => void
const tasksAfterRender: (Task)[] = []
const visibleNodesGenerator = new VisibleNodesGenerator()
const init: MethodCreator = dispatch => () => dispatch.call(setStateText, 'Fetching File List...')
const init: MethodCreator<Props, ConnectorState> = dispatch => () => dispatch.call(setStateText, 'Fetching File List...')
function resolveGitModules(root: TreeNode, blobData: BlobData) {
if (blobData) {
@ -58,8 +58,8 @@ function resolveGitModules(root: TreeNode, blobData: BlobData) {
}
}
const setUpTree: MethodCreator<Props> = dispatch => () =>
dispatch.get(async ({ treeData, metaData, compressSingletonFolder, accessToken }) => {
const setUpTree: MethodCreator<Props, ConnectorState> = dispatch => () =>
dispatch.get(async (_, { treeData, metaData, compressSingletonFolder, accessToken }) => {
if (!treeData) return
dispatch.call(setStateText, 'Rendering File List...')
const { root, gitModules } = treeParser.parse(treeData, metaData)
@ -92,20 +92,20 @@ const setUpTree: MethodCreator<Props> = dispatch => () =>
dispatch.call(updateVisibleNodes)
})
const execAfterRender: MethodCreator = dispatch => () => {
const execAfterRender: MethodCreator<Props, ConnectorState> = dispatch => () => {
for (const task of tasksAfterRender) {
task()
}
tasksAfterRender.length = 0
}
const setStateText: MethodCreator<Props> = dispatch => (text: string) =>
const setStateText: MethodCreator<Props, ConnectorState> = dispatch => (text: string) =>
dispatch.set({
stateText: text,
})
const handleKeyDown: MethodCreator = dispatch => event =>
dispatch.get((_, { visibleNodes: { nodes, focusedNode, expandedNodes, depths } }) => {
const handleKeyDown: MethodCreator<Props, ConnectorState> = dispatch => event =>
dispatch.get(({ visibleNodes: { nodes, focusedNode, expandedNodes, depths } }) => {
function handleVerticalMove(index: number) {
if (0 <= index && index < nodes.length) {
DOMHelper.focusFileExplorer()
@ -201,9 +201,9 @@ const handleKeyDown: MethodCreator = dispatch => event =>
}
})
const onFocusSearchBar: MethodCreator = dispatch => () => dispatch.call(focusNode, null)
const onFocusSearchBar: MethodCreator<Props, ConnectorState> = dispatch => () => dispatch.call(focusNode, null)
const handleSearchKeyChange: MethodCreator = dispatch => {
const handleSearchKeyChange: MethodCreator<Props, ConnectorState> = dispatch => {
let i = 0
return async event => {
const searchKey = event.target.value
@ -221,7 +221,7 @@ function shouldDelayExpand(node: TreeNode) {
)
}
const setExpand: MethodCreator = dispatch => (node, expand) => {
const setExpand: MethodCreator<Props, ConnectorState> = dispatch => (node, expand) => {
visibleNodesGenerator.setExpand(node, expand)
const applyChanges = () => dispatch.call(focusNode, node)
if (shouldDelayExpand(node)) {
@ -232,7 +232,7 @@ const setExpand: MethodCreator = dispatch => (node, expand) => {
}
}
const toggleNodeExpansion: MethodCreator = dispatch => (node, skipScrollToNode) => {
const toggleNodeExpansion: MethodCreator<Props, ConnectorState> = dispatch => (node, skipScrollToNode) => {
visibleNodesGenerator.toggleExpand(node)
const applyChanges = () => {
dispatch.call(focusNode, node, skipScrollToNode)
@ -246,8 +246,8 @@ const toggleNodeExpansion: MethodCreator = dispatch => (node, skipScrollToNode)
}
}
const focusNode: MethodCreator = dispatch => (node, skipScroll) =>
dispatch.get((_, { visibleNodes: { nodes } }) => {
const focusNode: MethodCreator<Props, ConnectorState> = dispatch => (node, skipScroll) =>
dispatch.get(({ visibleNodes: { nodes } }) => {
visibleNodesGenerator.focusNode(node)
if (node && !skipScroll) {
// when focus a node not in viewport(by keyboard), scroll to it
@ -257,7 +257,7 @@ const focusNode: MethodCreator = dispatch => (node, skipScroll) =>
dispatch.call(updateVisibleNodes)
})
const onNodeClick: MethodCreator = dispatch => node => {
const onNodeClick: MethodCreator<Props, ConnectorState> = dispatch => node => {
if (node.type === 'tree') {
dispatch.call(toggleNodeExpansion, node, true)
} else if (node.type === 'blob') {
@ -268,8 +268,8 @@ const onNodeClick: MethodCreator = dispatch => node => {
}
}
const mountExpandingIndicator: MethodCreator = dispatch => node =>
dispatch.get((_, { visibleNodes }) => {
const mountExpandingIndicator: MethodCreator<Props, ConnectorState> = dispatch => node =>
dispatch.get(({ visibleNodes }) => {
const dummyVisibleNodes = {
...visibleNodes,
nodes: visibleNodes.nodes.slice(),
@ -285,7 +285,7 @@ const mountExpandingIndicator: MethodCreator = dispatch => node =>
})
})
const updateVisibleNodes: MethodCreator = dispatch => () => {
const updateVisibleNodes: MethodCreator<Props, ConnectorState> = dispatch => () => {
const { visibleNodes } = visibleNodesGenerator
dispatch.set({ visibleNodes })
}

View file

@ -51,7 +51,7 @@ export type ConnectorState = {
setCompressSingleton: SettingsBar['props']['setCompressSingleton']
}
const init: MethodCreator<Props> = dispatch => async () => {
const init: MethodCreator<Props, ConnectorState> = dispatch => async () => {
try {
if (!URLHelper.isInRepoPage()) return
dispatch.set({
@ -133,7 +133,7 @@ const init: MethodCreator<Props> = dispatch => async () => {
}
}
const handleError: MethodCreator = dispatch => async err => {
const handleError: MethodCreator<Props, ConnectorState> = dispatch => async err => {
if (err.message === EMPTY_PROJECT) {
dispatch.call(setError, 'This project seems to be empty.')
} else if (
@ -149,8 +149,8 @@ const handleError: MethodCreator = dispatch => async err => {
}
}
const onPJAXEnd: MethodCreator<ConnectorState> = dispatch => () => {
dispatch.get((_, { metaData, copyFileButton, copySnippetButton }) => {
const onPJAXEnd: MethodCreator<Props, ConnectorState> = dispatch => () => {
dispatch.get(({ metaData, copyFileButton, copySnippetButton }) => {
DOMHelper.unmountTopProgressBar()
DOMHelper.decorateGitHubPageContent({ copyFileButton, copySnippetButton })
const mergedMetaData = { ...metaData, ...URLHelper.parse() }
@ -159,8 +159,8 @@ const onPJAXEnd: MethodCreator<ConnectorState> = dispatch => () => {
})
}
const onKeyDown: MethodCreator = dispatch => e => {
dispatch.set(({ toggleShowSideBarShortcut }: { toggleShowSideBarShortcut: string }) => {
const onKeyDown: MethodCreator<Props, ConnectorState> = dispatch => e => {
dispatch.get(({ toggleShowSideBarShortcut }) => {
if (toggleShowSideBarShortcut) {
const keys = keyHelper.parseEvent(e)
if (keys === toggleShowSideBarShortcut) {
@ -170,41 +170,41 @@ const onKeyDown: MethodCreator = dispatch => e => {
})
}
const toggleShowSideBar: MethodCreator = dispatch => () =>
dispatch.set(({ shouldShow }: { shouldShow: boolean }) =>
const toggleShowSideBar: MethodCreator<Props, ConnectorState> = dispatch => () =>
dispatch.get(({ shouldShow }) =>
dispatch.call(setShouldShow, !shouldShow)
)
const setShouldShow: MethodCreator = dispatch => shouldShow => {
const setShouldShow: MethodCreator<Props, ConnectorState> = dispatch => shouldShow => {
dispatch.set({ shouldShow }, shouldShow ? DOMHelper.focusFileExplorer : null)
DOMHelper.setBodyIndent(shouldShow)
}
const setError: MethodCreator = dispatch => error => {
const setError: MethodCreator<Props, ConnectorState> = dispatch => error => {
dispatch.set({ error })
dispatch.call(setShouldShow, false)
}
const toggleShowSettings: MethodCreator = dispatch => () =>
dispatch.set(({ showSettings }: { showSettings: boolean }) => ({
const toggleShowSettings: MethodCreator<Props, ConnectorState> = dispatch => () =>
dispatch.set(({ showSettings }) => ({
showSettings: !showSettings,
}))
const setShowSettings: MethodCreator = dispatch => showSettings => dispatch.set({ showSettings })
const setShowSettings: MethodCreator<Props, ConnectorState> = dispatch => showSettings => dispatch.set({ showSettings })
const onAccessTokenChange: MethodCreator = dispatch => accessToken => dispatch.set({ accessToken })
const onAccessTokenChange: MethodCreator<Props, ConnectorState> = dispatch => accessToken => dispatch.set({ accessToken })
const onShortcutChange: MethodCreator = dispatch => shortcut =>
const onShortcutChange: MethodCreator<Props, ConnectorState> = dispatch => shortcut =>
dispatch.set({ toggleShowSideBarShortcut: shortcut })
const setMetaData: MethodCreator = dispatch => metaData => dispatch.set({ metaData })
const setMetaData: MethodCreator<Props, ConnectorState> = dispatch => metaData => dispatch.set({ metaData })
const setCompressSingleton: MethodCreator = dispatch => compressSingletonFolder =>
const setCompressSingleton: MethodCreator<Props, ConnectorState> = dispatch => compressSingletonFolder =>
dispatch.set({ compressSingletonFolder })
const setCopyFile: MethodCreator = dispatch => copyFileButton => dispatch.set({ copyFileButton })
const setCopyFile: MethodCreator<Props, ConnectorState> = dispatch => copyFileButton => dispatch.set({ copyFileButton })
const setCopySnippet: MethodCreator = dispatch => copySnippetButton =>
const setCopySnippet: MethodCreator<Props, ConnectorState> = dispatch => copySnippetButton =>
dispatch.set({ copySnippetButton })
export default {