Description
Bug Report
π Search Terms
conditional types, generics
π Version & Regression Information
- Seems to be broken in every version available in TS playground
β― Playground Link
Playground link with relevant code
π» Code
interface PayloadMap {
hello: string,
none: never,
}
type Payload<T extends PayloadMap, K extends keyof T> = T[K] extends never ? [] : [payload: T[K]];
class Base<T extends PayloadMap = PayloadMap> {
emit<K extends keyof T>(type: K, ...payload: Payload<T, K>): Base<T> {
return this;
}
}
class Implementation<T extends PayloadMap = PayloadMap> extends Base<T> {
constructor() {
super();
this.emit('hello', 'asdf'); // Argument of type '["asdf"]' is not assignable to parameter of type 'Payload<T, "hello">'.(2345)
this.emit('none'); // Argument of type '[]' is not assignable to parameter of type 'Payload<T, "none">'.(2345)
}
}
// all following `emit` calls are fine
let impl = {} as Implementation<{test: string} & PayloadMap>;
impl.emit('hello', 'asdf');
impl.emit('none');
impl.emit('test', 'asdf');
class GenericlessImplementation extends Base<{test: string} & PayloadMap> {
constructor() {
super();
this.emit('hello', 'asdf');
this.emit('none');
this.emit('test', 'asdf');
}
}
π Actual behavior
This code example doesn't compile and I think it should as the generic is always constraint to PayloadMap
.
π Expected behavior
The example has compile errors because compiler is unable to find out that T is always compatible with PayloadMap
.
Some context for the issue I'm dealing with - I'm trying to change typings to a base class we have in our library that is responsible for emitting events and acts as a base class for all other objects that need to emit events in the lib. We have an interface with eventName: PayloadType
mapping - it basically defines all events that we emit and what payloads they have. This map is currently static but we want to make it generic so that users of the library can extend it and emit custom events. We need to support events with no payload - those are represneted by the never
type. If the payload is never, emit
function should be callable only with one argument, if the payload is any other type, the emit function has to be called with 2 arguments - that's what the Payload
type does (and it works well - until we introduce generics).
I was looking at this bug report as well but it seems to be about something different, but I'm not 100% sure - #33369.