fix: 🐛 fix eslint errors

This commit is contained in:
bubkoo
2021-03-22 21:48:12 +08:00
committed by 问崖
parent 35c2a8927c
commit 052fe61481
42 changed files with 98 additions and 76 deletions

View File

@ -12,7 +12,7 @@
"lint": "eslint 'src/**/*.{js,ts}?(x)' --fix",
"build": "tsc --outDir ./lib",
"build:watch": "yarn build --w",
"prebuild": "run-s clean",
"prebuild": "run-s lint clean",
"preinstall": "run-s build",
"precommit": "lint-staged"
},
@ -30,7 +30,7 @@
"@typescript-eslint/eslint-plugin": "^4.18.0",
"@typescript-eslint/parser": "^4.18.0",
"eslint": "^7.22.0",
"eslint-config-airbnb-typescript": "^12.3.1",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-import": "^2.22.1",

View File

@ -1,14 +0,0 @@
{
"extends": "../../.eslintrc",
"rules": {
"new-cap": 0,
"no-bitwise": 0,
"guard-for-in": 0,
"@typescript-eslint/no-unused-vars": 0,
"no-underscore-dangle": 0,
"no-restricted-syntax": 0,
"no-restricted-globals": 0,
"@typescript-eslint/ban-types": 0,
"@typescript-eslint/no-redeclare": 0
}
}

View File

@ -91,7 +91,7 @@
"@typescript-eslint/parser": "^4.18.0",
"coveralls": "^3.1.0",
"eslint": "^7.22.0",
"eslint-config-airbnb-typescript": "^12.3.1",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-import": "^2.22.1",

View File

@ -96,7 +96,7 @@ export class Widget<
this.init(localOptions)
}
protected init(options: Options) {}
protected init(options: Options) {} // eslint-disable-line
protected render() {
return this

View File

@ -11,8 +11,6 @@ import { Handle } from '../common'
import { notify } from '../transform/util'
import { Halo } from './index'
export function getNodePreset(halo: Halo) {}
export class NodePreset {
private edgeView: EdgeView | null
private flip: number

View File

@ -38,7 +38,7 @@ export class Scroller extends View {
protected cachedScrollTop: number | null
protected cachedCenterPoint: Point.PointLike | null
protected cachedClientSize: { width: number; height: number } | null
protected delegatedHandlers: { [name: string]: Function }
protected delegatedHandlers: { [name: string]: (...args: any) => any }
constructor(options: Scroller.Options) {
super()
@ -198,17 +198,17 @@ export class Scroller extends View {
protected delegateBackgroundEvents(events?: View.Events) {
const evts = events || GraphView.events
this.delegatedHandlers = Object.keys(evts).reduce<{
[name: string]: Function
[name: string]: (...args: any) => any
}>((memo, name) => {
const handler = evts[name]
if (name.indexOf(' ') === -1) {
if (typeof handler === 'function') {
memo[name] = handler
memo[name] = handler as (...args: any) => any
} else {
let method = this.graph.view[handler as keyof GraphView]
if (typeof method === 'function') {
method = method.bind(this.graph.view)
memo[name] = method as Function
memo[name] = method as (...args: any) => any
}
}
}

View File

@ -7,7 +7,7 @@ export namespace Dijkstra {
export function run(
adjacencyList: AdjacencyList,
source: string,
weight: Weight = (u, v) => 1,
weight: Weight = (u, v) => 1, // eslint-disable-line
) {
const dist: { [key: string]: number } = {}
const previous: { [key: string]: string } = {}
@ -16,12 +16,12 @@ export namespace Dijkstra {
dist[source] = 0
for (const v in adjacencyList) {
Object.keys(adjacencyList).forEach((v) => {
if (v !== source) {
dist[v] = Infinity
}
queue.insert(dist[v], v, v)
}
})
while (!queue.isEmpty()) {
const u = queue.remove()!

View File

@ -309,7 +309,7 @@ export namespace Color {
function hex2rgb(hex: string): [number, number, number] {
const color = hex.indexOf('#') === 0 ? hex : `#${hex}`
let val = Number(`0x${color.substr(1)}`)
if (!(color.length === 4 || color.length === 7) || isNaN(val)) {
if (!(color.length === 4 || color.length === 7) || Number.isNaN(val)) {
throw new Error('Invalid hex color.')
}

View File

@ -1,6 +1,6 @@
import { Disposable } from './disposable'
export class Dictionary<T extends Object, V> extends Disposable {
export class Dictionary<T extends Record<string, any>, V> extends Disposable {
private map: WeakMap<T, V>
private arr: T[]

View File

@ -1,3 +1,5 @@
/* eslint-disable no-underscore-dangle */
import { Basecoat } from './basecoat'
export interface IDisablable {
@ -9,7 +11,6 @@ export interface IDisablable {
export abstract class Disablable<EventArgs = any>
extends Basecoat<EventArgs>
implements IDisablable {
// eslint-disable-next-line
private _disabled?: boolean
public get disabled(): boolean {

View File

@ -1,3 +1,5 @@
/* eslint-disable no-underscore-dangle */
/**
* An object which implements the disposable pattern.
*/

View File

@ -1147,7 +1147,7 @@ export class Path extends Geometry {
if (segment.isVisible) {
const divisions = segmentSubdivisions[i]
if (divisions.length > 0) {
// eslint-disable-next-line @typescript-eslint/no-loop-func
// eslint-disable-next-line no-loop-func
divisions.forEach((c) => partialPoints.push(c.start))
} else {
partialPoints.push(segment.start)

View File

@ -42,7 +42,7 @@ export abstract class Segment extends Geometry {
closestPointT(
p: Point.PointLike | Point.PointData,
options?: Segment.Options,
options?: Segment.Options, // eslint-disable-line
) {
if (this.closestPointNormalizedLength) {
return this.closestPointNormalizedLength(p)
@ -59,6 +59,7 @@ export abstract class Segment extends Geometry {
abstract length(options?: Segment.Options): number
// eslint-disable-next-line
lengthAtT(t: number, options?: Segment.Options) {
if (t <= 0) {
return 0

View File

@ -30,11 +30,11 @@ export function random(min?: number, max?: number): number {
}
export function clamp(value: number, min: number, max: number) {
if (isNaN(value)) {
if (Number.isNaN(value)) {
return NaN
}
if (isNaN(min) || isNaN(max)) {
if (Number.isNaN(min) || Number.isNaN(max)) {
return 0
}

View File

@ -215,7 +215,7 @@ export class FormatManager extends Base {
: viewBox
let scale = options.ratio ? parseFloat(options.ratio) : 1
if (!isFinite(scale) || scale === 0) {
if (!Number.isFinite(scale) || scale === 0) {
scale = 1
}

View File

@ -1979,6 +1979,7 @@ export class Graph extends Basecoat<EventArgs> {
}
export namespace Graph {
/* eslint-disable @typescript-eslint/no-unused-vars */
export import View = GraphView
export import Hook = HookManager
export import Renderer = ViewRenderer

View File

@ -369,6 +369,7 @@ export class HistoryManager
* is called every change made on model is not stored into the undoStack.
* Changes are temporarily kept until `storeBatchCommand()` is called.
*/
// eslint-disable-next-line
protected initBatchCommand(options: KeyValue) {
if (this.freezed) {
return

View File

@ -297,6 +297,7 @@ export class Hook extends Base implements Hook.IHook {
}
@Decorator.hook()
// eslint-disable-next-line
allowRubberband(e: JQuery.MouseDownEvent) {
return true
}
@ -320,6 +321,7 @@ export class Hook extends Base implements Hook.IHook {
}
@Decorator.hook()
// eslint-disable-next-line
allowPanning(e: JQuery.MouseDownEvent) {
return true
}
@ -665,14 +667,14 @@ export class Hook extends Base implements Hook.IHook {
onViewPostponed(
view: CellView,
flag: number,
options: Renderer.UpdateViewOptions,
options: Renderer.UpdateViewOptions, // eslint-disable-line
) {
return this.graph.renderer.forcePostponedViewUpdate(view, flag)
}
@Decorator.hook()
getCellView(
cell: Cell,
cell: Cell, // eslint-disable-line
): null | undefined | typeof CellView | (new (...args: any[]) => CellView) {
return null
}
@ -683,14 +685,14 @@ export class Hook extends Base implements Hook.IHook {
const ctor = this.getCellView(cell)
if (ctor) {
return new ctor(cell, options)
return new ctor(cell, options) // eslint-disable-line new-cap
}
const view = cell.view
if (view != null && typeof view === 'string') {
const def = CellView.registry.get(view)
if (def) {
return new def(cell, options)
return new def(cell, options) // eslint-disable-line new-cap
}
return CellView.registry.onNotFound(view)
@ -749,13 +751,13 @@ export class Hook extends Base implements Hook.IHook {
}
@Decorator.hook()
onEdgeLabelRendered(args: Hook.OnEdgeLabelRenderedArgs) {}
onEdgeLabelRendered(args: Hook.OnEdgeLabelRenderedArgs) {} // eslint-disable-line
@Decorator.hook()
onPortRendered(args: Hook.OnPortRenderedArgs) {}
onPortRendered(args: Hook.OnPortRenderedArgs) {} // eslint-disable-line
@Decorator.hook()
onToolItemCreated(args: Hook.OnToolItemCreatedArgs) {}
onToolItemCreated(args: Hook.OnToolItemCreatedArgs) {} // eslint-disable-line
}
export namespace Hook {

View File

@ -71,6 +71,7 @@ export class PanningManager extends Base {
this.graph.translateBy(dx, dy)
}
// eslint-disable-next-line
protected stopPanning(e: JQuery.MouseUpEvent) {
this.panning = false
this.updateClassName()

View File

@ -432,9 +432,11 @@ export class Renderer extends Base {
checkView = null
}
// eslint-disable-next-line no-labels
// eslint-disable-next-line
main: for (let p = 0, n = priorities.length; p < n; p += 1) {
const cache = priorities[p]
// eslint-disable-next-line
for (const cid in cache) {
if (updatedCount >= batchSize) {
empty = false // goto next batch
@ -1046,6 +1048,7 @@ export class Renderer extends Base {
pivot = pivots[zIndex] = document.createComment(`z-index:${zIndex + 1}`)
let neighborZ = -Infinity
// eslint-disable-next-line
for (const key in pivots) {
const currentZ = +key
if (currentZ < zIndex && currentZ > neighborZ) {

View File

@ -1,3 +1,5 @@
/* eslint-disable no-underscore-dangle */
import { NonUndefined } from 'utility-types'
import { ArrayExt, StringExt, ObjectExt, FunctionExt } from '../util'
import { Rectangle, Point } from '../geometry'
@ -140,7 +142,7 @@ export class Cell<
return props as Properties
}
protected postprocess(metadata: Cell.Metadata) {}
protected postprocess(metadata: Cell.Metadata) {} // eslint-disable-line
protected setup() {
this.store.on('change:*', (metadata) => {
@ -710,7 +712,7 @@ export class Cell<
if (options.overwrite === true) {
set(data)
} else {
const prev = this.getData<Object>()
const prev = this.getData<Record<string, any>>()
if (options.deep === false) {
set(typeof data === 'object' ? { ...prev, ...data } : data)
} else {
@ -1112,15 +1114,16 @@ export class Cell<
// #region transform
// eslint-disable-next-line
translate(tx: number, ty: number, options?: Cell.TranslateOptions) {
return this
}
scale(
sx: number,
sy: number,
origin?: Point | Point.PointLike,
options?: Node.SetOptions,
sx: number, // eslint-disable-line
sy: number, // eslint-disable-line
origin?: Point | Point.PointLike, // eslint-disable-line
options?: Node.SetOptions, // eslint-disable-line
) {
return this
}
@ -1236,10 +1239,12 @@ export class Cell<
// #region common
// eslint-disable-next-line
getBBox(options?: { deep?: boolean }) {
return new Rectangle()
}
// eslint-disable-next-line
getConnectionPoint(edge: Edge, type: Edge.TerminalType) {
return new Point()
}
@ -1368,7 +1373,7 @@ export class Cell<
delete data.parent
delete data.children
const ctor = this.constructor as typeof Cell
return new ctor(data) as any
return new ctor(data) as any // eslint-disable-line new-cap
}
// Deep cloning. Clone the cell itself and all its children.

View File

@ -506,7 +506,7 @@ export class Edge<
) {
const labels = this.getLabels()
const len = labels.length
let idx = index != null && isFinite(index) ? index : len
let idx = index != null && Number.isFinite(index) ? index : len
if (idx < 0) {
idx = len + idx + 1
}
@ -521,7 +521,7 @@ export class Edge<
getLabelAt(index: number) {
const labels = this.getLabels()
if (index != null && isFinite(index)) {
if (index != null && Number.isFinite(index)) {
return this.parseLabel(labels[index])
}
return null
@ -532,7 +532,7 @@ export class Edge<
label: Edge.Label | string,
options: Edge.SetOptions = {},
) {
if (index != null && isFinite(index)) {
if (index != null && Number.isFinite(index)) {
const labels = this.getLabels()
labels[index] = this.parseLabel(label)
this.setLabels(labels, options)
@ -542,7 +542,7 @@ export class Edge<
removeLabelAt(index: number, options: Edge.SetOptions = {}) {
const labels = this.getLabels()
const idx = index != null && isFinite(index) ? index : -1
const idx = index != null && Number.isFinite(index) ? index : -1
const removed = labels.splice(idx, 1)
this.setLabels(labels, options)
@ -661,7 +661,7 @@ export class Edge<
) {
const vertices = this.getVertices()
const len = vertices.length
let idx = index != null && isFinite(index) ? index : len
let idx = index != null && Number.isFinite(index) ? index : len
if (idx < 0) {
idx = len + idx + 1
}
@ -675,7 +675,7 @@ export class Edge<
}
getVertexAt(index: number) {
if (index != null && isFinite(index)) {
if (index != null && Number.isFinite(index)) {
const vertices = this.getVertices()
return vertices[index]
}
@ -687,7 +687,7 @@ export class Edge<
vertice: Point.PointLike,
options: Edge.SetOptions = {},
) {
if (index != null && isFinite(index)) {
if (index != null && Number.isFinite(index)) {
const vertices = this.getVertices()
vertices[index] = vertice
this.setVertices(vertices, options)
@ -697,7 +697,7 @@ export class Edge<
removeVertexAt(index: number, options: Edge.SetOptions = {}) {
const vertices = this.getVertices()
const idx = index != null && isFinite(index) ? index : -1
const idx = index != null && Number.isFinite(index) ? index : -1
vertices.splice(idx, 1)
return this.setVertices(vertices, options)
}
@ -956,6 +956,7 @@ export class Edge<
// Note that there in the deep mode a edge can have a loop,
// even if it connects only a parent and its embed.
// A loop "target equals source" is valid in both shallow and deep mode.
// eslint-disable-next-line
if (!loop && options.deep && this._model) {
const sourceCell = this.getSourceCell()
const targetCell = this.getTargetCell()

View File

@ -159,6 +159,7 @@ export class Store<D> extends Basecoat<Store.EventArgs<D>> {
key.forEach((k) => (subset[k] = empty))
opts = options
} else {
// eslint-disable-next-line
for (const key in this.data) {
subset[key] = empty
}
@ -269,6 +270,7 @@ export class Store<D> extends Basecoat<Store.EventArgs<D>> {
const old = this.changing ? this.previous : this.data
const changed: Partial<D> = {}
let hasChanged
// eslint-disable-next-line
for (const key in diff) {
const val = diff[key]
if (!ObjectExt.isEqual(old[key], val)) {

View File

@ -32,7 +32,7 @@ function offsetWrapper(
delta = refBBox[dimension] / 2
} else if (value === corner) {
delta = refBBox[dimension]
} else if (typeof value === 'number' && isFinite(value)) {
} else if (typeof value === 'number' && Number.isFinite(value)) {
delta = value > -1 && value < 1 ? -refBBox[dimension] * value : -value
} else if (NumberExt.isPercentage(value)) {
delta = (refBBox[dimension] * parseFloat(value)) / 100

View File

@ -11,7 +11,7 @@ export const connection: Attr.Definition = {
const view = args.view as EdgeView
const stubs = ((val as any).stubs || 0) as number
let d
if (isFinite(stubs) && stubs !== 0) {
if (Number.isFinite(stubs) && stubs !== 0) {
let offset
if (stubs < 0) {
const len = view.getConnectionLength() || 0

View File

@ -95,7 +95,7 @@ function normalizeAttr(
const strokeWidth = parseFloat(
(attr.strokeWidth || attr['stroke-width']) as string,
)
if (isFinite(strokeWidth) && strokeWidth > 1) {
if (Number.isFinite(strokeWidth) && strokeWidth > 1) {
const offset = Math.ceil(strokeWidth / 2)
result.refX = type === 'marker-start' ? offset : -offset
}

View File

@ -75,7 +75,7 @@ export const refRCircumscribed: Attr.Definition = {
)
let rValue
if (isFinite(value)) {
if (Number.isFinite(value)) {
if (percentage || (value >= 0 && value <= 1)) {
rValue = value * diagonalLength
} else {
@ -143,7 +143,7 @@ function positionWrapper(
}
let delta
if (isFinite(value)) {
if (Number.isFinite(value)) {
const refOrigin = refBBox[origin]
if (percentage || (value > 0 && value < 1)) {
delta = refOrigin[axis] + refBBox[dimension] * value
@ -171,7 +171,7 @@ function setWrapper(
const attrs: Attr.SimpleAttrs = {}
if (isFinite(value)) {
if (Number.isFinite(value)) {
const attrValue =
percentage || (value >= 0 && value <= 1)
? value * refBBox[dimension]

View File

@ -51,7 +51,7 @@ function alignLine(line: Line, type: Align, offset = 0) {
b[coordinate] = a[coordinate]
}
if (isFinite(offset)) {
if (Number.isFinite(offset)) {
a[coordinate] += direction * offset
b[coordinate] += direction * offset
}

View File

@ -7,7 +7,7 @@ export function offset(
) {
let tx: number | undefined
if (typeof offset === 'object') {
if (isFinite(offset.y)) {
if (Number.isFinite(offset.y)) {
const line = new Line(p2, p1)
const { start, end } = line.parallel(offset.y)
p2 = start // eslint-disable-line
@ -18,7 +18,7 @@ export function offset(
tx = offset
}
if (tx == null || !isFinite(tx)) {
if (tx == null || !Number.isFinite(tx)) {
return p1
}

View File

@ -13,7 +13,8 @@ export interface BlurArgs {
export function blur(args: BlurArgs = {}) {
const x = getNumber(args.x, 2)
const stdDeviation = args.y != null && isFinite(args.y) ? [x, args.y] : x
const stdDeviation =
args.y != null && Number.isFinite(args.y) ? [x, args.y] : x
return `
<filter>

View File

@ -9,5 +9,5 @@ export function getNumber(
num: number | null | undefined,
defaultValue: number,
) {
return num != null && isFinite(num) ? num : defaultValue
return num != null && Number.isFinite(num) ? num : defaultValue
}

View File

@ -28,7 +28,7 @@ const middleSide: NodeAnchor.ResolvedDefinition<MiddleSideEndpointOptions> = fun
}
const padding = options.padding
if (padding != null && isFinite(padding)) {
if (padding != null && Number.isFinite(padding)) {
bbox.inflate(padding)
}

View File

@ -6,6 +6,7 @@ export interface ResolveOptions {
fixedAt?: number | string
}
// eslint-disable-next-line
export function resolve<S extends Function, T>(fn: S): T {
return (function (
this: EdgeView,

View File

@ -59,7 +59,7 @@ export class Vertices extends ToolsView.ToolItem<EdgeView, Vertices.Options> {
const handle = createHandle({
index: i,
graph: this.graph,
guard: (evt: JQuery.TriggeredEvent) => this.guard(evt),
guard: (evt: JQuery.TriggeredEvent) => this.guard(evt), // eslint-disable-line no-loop-func
attrs: this.options.attrs || {},
})

View File

@ -1,5 +1,6 @@
export type ModifierKey = 'alt' | 'ctrl' | 'meta' | 'shift'
// eslint-disable-next-line
export namespace ModifierKey {
export function parse(modifiers: string | ModifierKey[]) {
const or: ModifierKey[] = []

View File

@ -15,8 +15,8 @@ describe('DataUri', () => {
describe('#imageToDataUri', () => {
const oldXMLHttpRequest = window.XMLHttpRequest
const oldFileReader = window.FileReader
let onLoadHandle: () => {}
let onErrorHandle: () => {}
let onLoadHandle: () => Record<string, any>
let onErrorHandle: () => Record<string, any>
beforeEach(() => {
const win = window as any

View File

@ -249,6 +249,7 @@ describe('Dom', () => {
describe('#matrixTo[Transformation]', () => {
function roundObject(obj: any) {
// eslint-disable-next-line
for (const i in obj) {
if (Object.prototype.hasOwnProperty.call(obj, i)) {
obj[i] = Math.round(obj[i])

View File

@ -211,6 +211,7 @@ export namespace JSONExt {
}
// Check for the first object's keys in the second object.
// eslint-disable-next-line
for (const key in first) {
if (!(key in second)) {
return false
@ -218,6 +219,7 @@ export namespace JSONExt {
}
// Check for the second object's keys in the first object.
// eslint-disable-next-line
for (const key in second) {
if (!(key in first)) {
return false
@ -225,6 +227,7 @@ export namespace JSONExt {
}
// Compare the values for equality.
// eslint-disable-next-line
for (const key in first) {
if (!deepEqual(first[key], second[key])) {
return false

View File

@ -16,6 +16,7 @@ const extendStatics =
/**
* @see https://github.com/microsoft/TypeScript/blob/5c85febb0ce9d6088cbe9b09cb42f73f9ee8ea05/src/compiler/transformers/es2015.ts#L4309
*/
// eslint-disable-next-line
export function inherit(cls: Function, base: Function) {
extendStatics(cls, base)
function tmp() {
@ -34,15 +35,16 @@ const isNativeClass =
/**
* Extends class with specified class name.
*/
// eslint-disable-next-line
export function createClass<T>(className: string, base: Function): T {
let cls
if (isNativeClass) {
// eslint-disable-next-line @typescript-eslint/no-implied-eval
// eslint-disable-next-line no-new-func
cls = new Function('base', `return class ${className} extends base { }`)(
base,
)
} else {
// eslint-disable-next-line @typescript-eslint/no-implied-eval
// eslint-disable-next-line no-new-func
cls = new Function(
'base',
`return function ${className}() { return base.apply(this, arguments) }`,

View File

@ -25,6 +25,7 @@ const supportedUnits = {
export type Unit = keyof typeof supportedUnits
// eslint-disable-next-line
export namespace Unit {
export function measure(cssWidth: string, cssHeight: string, unit?: Unit) {
const div = jQuery('<div/>')

View File

@ -5,6 +5,7 @@ import { ObjectExt, StringExt, Dom, Vector } from '../util'
export type Markup = string | Markup.JSONMarkup | Markup.JSONMarkup[]
// eslint-disable-next-line
export namespace Markup {
export type Selectors = KeyValue<Element | Element[]>
@ -51,6 +52,7 @@ export namespace Markup {
}
}
// eslint-disable-next-line
export namespace Markup {
export function isJSONMarkup(markup?: Nilable<Markup>) {
return markup != null && !isStringMarkup(markup)
@ -267,6 +269,7 @@ export namespace Markup {
}
}
// eslint-disable-next-line
export namespace Markup {
export function getSelector(
elem: Element,
@ -457,6 +460,7 @@ export namespace Markup {
}
}
// eslint-disable-next-line
export namespace Markup {
export function getPortContainerMarkup(): Markup {
return 'g'
@ -485,6 +489,7 @@ export namespace Markup {
}
}
// eslint-disable-next-line
export namespace Markup {
export function getEdgeMarkup(): Markup {
return sanitize(`
@ -537,6 +542,7 @@ export namespace Markup {
}
}
// eslint-disable-next-line
export namespace Markup {
export function getForeignObjectMarkup(bare = false): Markup.JSONMarkup {
return {

View File

@ -287,7 +287,9 @@ export abstract class View<EventArgs = any> extends Basecoat<EventArgs> {
return `.${Config.prefixCls}-event-${this.cid}`
}
// eslint-disable-next-line
protected getEventHandler(handler: string | Function) {
// eslint-disable-next-line
let method: Function | undefined
if (typeof handler === 'string') {
const fn = (this as any)[handler]
@ -372,7 +374,7 @@ export abstract class View<EventArgs = any> extends Basecoat<EventArgs> {
}
export namespace View {
export type Events = KeyValue<string | Function>
export type Events = KeyValue<string | Function> // eslint-disable-line
}
export namespace View {