UNPKG

chrome-devtools-frontend

Version:
166 lines (127 loc) 6.13 kB
// Copyright 2021 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Important: This code does not actually run any tests but is used to verify // that the type magic of `EventTarget` behaves as expected w.r.t // to the TypeScript compiler. import * as Common from './common.js'; const enum Events { VOID_EVENT = 'VoidEvent', NUMBER_EVENT = 'NumberEvent', KEY_VALUE_EVENT = 'KeyValueEvent', BOOLEAN_EVENT = 'BooleanEvent', UNION_EVENT = 'UnionEvent', } interface TestEvents { [Events.VOID_EVENT]: void; [Events.NUMBER_EVENT]: number; [Events.KEY_VALUE_EVENT]: {key: string, value: number}; [Events.BOOLEAN_EVENT]: boolean; [Events.UNION_EVENT]: string|null; } class TypedEventEmitter extends Common.ObjectWrapper.ObjectWrapper<TestEvents> { testValidArgumentTypes() { this.dispatchEventToListeners(Events.VOID_EVENT); this.dispatchEventToListeners(Events.NUMBER_EVENT, 5.0); this.dispatchEventToListeners(Events.KEY_VALUE_EVENT, {key: 'key', value: 42}); this.dispatchEventToListeners(Events.BOOLEAN_EVENT, true); this.dispatchEventToListeners(Events.UNION_EVENT, 'foo'); this.dispatchEventToListeners(Events.UNION_EVENT, null); } testInvalidArgumentTypes() { // @ts-expect-error undefined instead of no argument provided this.dispatchEventToListeners(Events.VOID_EVENT, undefined); // @ts-expect-error string instead of undefined provided this.dispatchEventToListeners(Events.VOID_EVENT, 'void'); // @ts-expect-error string instead of number provided this.dispatchEventToListeners(Events.NUMBER_EVENT, 'expected number'); // @ts-expect-error argument missing this.dispatchEventToListeners(Events.NUMBER_EVENT); // @ts-expect-error wrong object type provided as payload this.dispatchEventToListeners(Events.KEY_VALUE_EVENT, {key: 'key', foo: 'foo'}); // @ts-expect-error unknown event type used this.dispatchEventToListeners('fake', {key: 'key', foo: 'foo'}); // @ts-expect-error wrong payload not part of the union this.dispatchEventToListeners(Events.UNION_EVENT, 25); } testStringAndSymbolDisallowed() { // @ts-expect-error only keys of `TestEvents` are allowed. this.dispatchEventToListeners('foo'); // @ts-expect-error only keys of `TestEvents` are allowed. this.dispatchEventToListeners(Symbol('foo')); } } class VoidTypedEventEmitter extends Common.ObjectWrapper.ObjectWrapper<void> { testInvalidArgumentTypes() { // @ts-expect-error undefined instead of no argument provided this.dispatchEventToListeners(Events.VOID_EVENT, undefined); // @ts-expect-error string instead of undefined provided this.dispatchEventToListeners(Events.VOID_EVENT, 'void'); // @ts-expect-error string instead of number provided this.dispatchEventToListeners(Events.NUMBER_EVENT, 'expected number'); // @ts-expect-error argument missing this.dispatchEventToListeners(Events.NUMBER_EVENT); // @ts-expect-error wrong object type provided as payload this.dispatchEventToListeners(Events.KEY_VALUE_EVENT, {key: 'key', foo: 'foo'}); // @ts-expect-error unknown event type used this.dispatchEventToListeners('fake', {key: 'key', foo: 'foo'}); // @ts-expect-error wrong payload not part of the union this.dispatchEventToListeners(Events.UNION_EVENT, 25); } testStringAndSymbolDisallowed() { // @ts-expect-error only keys of `TestEvents` are allowed. this.dispatchEventToListeners('foo'); // @ts-expect-error only keys of `TestEvents` are allowed. this.dispatchEventToListeners(Symbol('foo')); } } VoidTypedEventEmitter; // eslint-disable-next-line @typescript-eslint/no-explicit-any class UntypedEventEmitter extends Common.ObjectWrapper.ObjectWrapper<any> { testDispatch() { this.dispatchEventToListeners('foo'); this.dispatchEventToListeners(Symbol('number payload'), 25); this.dispatchEventToListeners(Events.VOID_EVENT); this.dispatchEventToListeners(Events.UNION_EVENT, 'foo'); } } function genericListener<T>(): (arg: Common.EventTarget.EventTargetEvent<T>) => void { return (_arg: Common.EventTarget.EventTargetEvent<T>) => {}; } const typedEmitter = new TypedEventEmitter(); (function testValidListeners() { typedEmitter.addEventListener(Events.VOID_EVENT, genericListener<void>()); typedEmitter.addEventListener(Events.NUMBER_EVENT, genericListener<number>()); typedEmitter.addEventListener(Events.KEY_VALUE_EVENT, genericListener<{key: string, value: number}>()); typedEmitter.addEventListener(Events.BOOLEAN_EVENT, genericListener<boolean>()); typedEmitter.addEventListener(Events.UNION_EVENT, genericListener<string|null>()); })(); (function testInvalidListenerArguments() { // @ts-expect-error typedEmitter.addEventListener(Events.VOID_EVENT, genericListener<number>()); // @ts-expect-error typedEmitter.addEventListener(Events.NUMBER_EVENT, genericListener<void>()); // @ts-expect-error typedEmitter.addEventListener(Events.KEY_VALUE_EVENT, genericListener<{foo: string}>()); // @ts-expect-error typedEmitter.addEventListener(Events.UNION_EVENT, genericListener<string>()); })(); (function testInvalidListenerType() { // @ts-expect-error typedEmitter.addEventListener('foo', genericListener()); // @ts-expect-error typedEmitter.addEventListener(Symbol('foo'), genericListener()); })(); (function testUnionTypeOnDispatch() { // @ts-expect-error typedEmitter.dispatchEventToListeners<Events.VOID_EVENT|Events.NUMBER_EVENT>(Events.NUMBER_EVENT, 5); const event: Events = Math.random() < 0.5 ? Events.NUMBER_EVENT : Events.BOOLEAN_EVENT; // @ts-expect-error typedEmitter.dispatchEventToListeners(event, true); })(); const untypedEmitter = new UntypedEventEmitter(); (function testUntypedListeners() { untypedEmitter.addEventListener('foo', genericListener()); untypedEmitter.addEventListener(Symbol('foo'), genericListener()); untypedEmitter.addEventListener(Events.VOID_EVENT, genericListener()); })();