Skip to content

Use string literal types to get rid of redundant overload definitions #6251

@kimamula

Description

@kimamula

Inspired by #1003 and #6028.
Isn't it possible to use string literal types for sharing specialized signatures among several methods?

i.e., I would like to write:

type TodoEvent = {
  name: 'create';
  payload: string;
} | {
  name: 'updateText';
  payload: {
    id: string;
    text: string;
  };
};

interface TodoEventEmitter {
  emit(name: TodoEvent.name, payload: TodoEvent.payload): boolean;
  on(name: TodoEvent.name, listener: (payload: TodoEvent.payload) => any): this;
  // ...etc
}

const eventEmitter: TodoEventEmitter = new EventEmitter();

instead of:

interface TodoEventEmitter {
  emit(name: 'create', payload: string): boolean;
  emit(name: 'updateText', payload: { id: string; text: string; }): boolean;
  emit(name: string, payload: any): boolean;

  on(name: 'craete', listener: (payload: string) => any): this; // typo 'craete', but no error
  on(name: 'updateText', listener: (payload: { id: number; text: string; }) => any): this; // id type incorrect, but no error
  on(name: string, listener: (payload: any) => any): this;

  // similar definitions for other methods again and again and again
}

const eventEmitter: TodoEventEmitter = new EventEmitter();

Overload definitions would be further reusable when used in combination with generic types.

interface EventEmitterBase<T extends {name: string, payload: any}> {
  // ...
}

const myEventEmitter: EventEmitterBase<MyEvent> = new EventEmitter();
const anotherEventEmitter: EventEmitterBase<AnotherEvent> = new EventEmitter();

Metadata

Metadata

Assignees

No one assigned

    Labels

    QuestionAn issue which isn't directly actionable in code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions