Typescript has a concept called ‘Declaration Merging’. The idea is that some kinds of declarations can be specified multiple times, and the ‘final’ or ‘actual’ value is the result of those combined declarations:
interface A { name: string }
interface A { age: number }
Here, we declare using declaration merging to define an interface that is the same as:
interface A { name: string; age: number }
This is really useful for writing code along with contextual, but global type information. Consider this example of defining Action types in the common reducer
pattern of event handling / dispatch:
enum ActionKind { }enum ActionKind { AddFile = 0 }
interface ActionAddFile {
type: ActionKind.AddFile
file: File
}enum ActionKind { DeleteFile = 1 }
interface ActionDeleteFile {
type: ActionKind.DeleteFile
file: File
}
We’ve nicely defined two action types: one, AddFile
adds a file, while the other DeleteFile
deletes a file. These can be uniquely identified by their ActionKind
.
Writing the actions this way avoids having to have a big enum ActionKind{ AddFile, DeleteFile, Something, SomethingElse }
which would have to be maintained separately to the actions themselves.
Almost always, however, we also want an Action
type that contains a union, to be discriminated on Action.type
, i.e:
type Action = ActionAddFile |…