my tsconfig.json has followed fields
"compilerOptions": {
...
"strictNullChecks": true,
"strict": true,
"alwaysStrict": true,
"noImplicitReturns": true,
"noImplicitThis": true,
...
}
and I designed the followed code
/*
constants in ./events
export const EVENT_NEED_MASK="EVENT_NEED_MASK"
export const EVENT_NO_MASK="EVENT_NO_MASK"
export const EVENT_FRAME_DRAWING_TRIGGERED="EVENT_FRAME_DRAWING_TRIGGERED"
export const EVENT_FRAME_DRAWING_SATRTED="EVENT_FRAME_DRAWING_SATRTED"
export const EVENT_FRAME_DRAWING_MOVING="EVENT_FRAME_DRAWING_MOVING"
...
*/
import * as EVENTS from "./events"
export type GlobalEventName = keyof GlobalEventHandlersEventMap
export type ExtendEventName =
keyof GlobalEventName
& keyof typeof EVENTS
export type EventEmitter = {
[prop in ExtendEventName]:EventListener
}
export function InstallEvent(e: EventEmitter, place:Window|HTMLElement = window) {
Object.keys(e).map(
(key:string ) => {
place.addEventListener(key, (x:Event) => {
e[key](x)
}
)
}
)
}
export type UserAction ={
AtBody?:EventEmitter,
AtShadowRoot?:EventEmitter
}
export let ActionSet: UserAction = {
AtBody: {
keydown: (e: KeyboardEvent) => {
},
mousedown: (e: MouseEvent & DomEvent) => {
},
mousemove: (e: MouseEvent & DomEvent) => {
},
mouseup: (e: MouseEvent & DomEvent) => {
},
click:(e: MouseEvent & DomEvent) =>{
}
},
AtShadowRoot: {
click: (e: MouseEvent & DomEvent) => {
},
mousedown: (e: MouseEvent & DomEvent) => {
},
dblclick: (e: MouseEvent & DomEvent) => {
}
}
}
export let InstallAction = (act: UserAction) => {
let place = {
AtBody: window,
AtShadowRoot: CORE.ShadowRoot
}
Object.keys(act).forEach((at) => {
InstallEvent(act[at], place[at])
})
}
My IDE told me that:
TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'EventEmitter'. No index signature with a parameter of type 'string' was found on type 'EventEmitter'.
I don't know how to fix this problem
CodePudding user response:
The problem is that your key
in Object.keys(e).map((key: string) => ...
is a type string
while EventEmitter
expects ExtendEventName
type.
The way I'd refactor this is to change ExtendedEventName
and EventEmitter
type to this:
export type ExtendEventName = keyof (GlobalEventHandlersEventMap & typeof EVENTS);
export type EventEmitter = Record<ExtendEventName | string, EventListener>;
As far as I know, there doesn't seem to be a way to iterate over a typed objects keys and have the key be typed. It'll always be string
unfortunately so we need to have string
fallback in the EventEmitter
key.
Edit: You can verify this by doing
for (const key in EventEmitter) {
// notice that `key` is type `string` not `ExtendEventName`
// although if you check `EventEmitter`
// it'll show all valid keys (`[key: ExtendEventName]: EventListener`).
// not `[key: string]: EventListener]`
}