Repository navigation
Feature: Extends doesn't constrain a generic typeΒ #47730
Description
Suggestion
π Search Terms
EventEmitter, extends, generics, nodejs, typescript, keyof, Objects, interface, constraints
β Viability Checklist
My suggestion meets these guidelines:
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- This feature would agree with the rest of TypeScript's Design Goals. (I'm pretty sure)
β Suggestion
Extends doesn't constrain the generic type, it just expects the type to have at least those qualities. I'd like to ensure that only the expected types are allowed. This is useful for things like a typed event emitter that loop over the keys of a generic. As it stands now, I have to get a bit ugly which may open up possible errors.
Having a constrainedby keyword or something similar would allow only generic types or child classes to be subclasses rather than extensions. This would allow child classes to still be considered children of their parents but more strict. However, extensions of the constrained child may try to override the parent so that still needs to be checked.
interface KeyListener {
[key: string]: Array<0|1>
}
// No errors
class TypedEmitter<C constrainedby KeyListener> extends EventEmitter {
on<T extends keyof C>(
event: T, listener: (...args: C[T])=>void
){
super.on(event, listener);
return this
}
}
const zero = Symbol("0");
const badInstance = new TypedEmitter<{ [zero]: [0,0,0,0], 1: [1,1,1,1] }>()
/*
Error, The generic C in TypedEmitter<C> is constrained by KeyListener, only specified keys are allowed
- [key: string]: Array<0|1>
Found Bad Keys
- [symbol("0")]: [0,0,0,0]
- 1: [1,1,1,1]
*/
interface BadChildInterface constrainedby KeyListener {
[zero]: [0,0,0,0],
1: [1,1,1,1]
/*
Error, BadChildInterface is constrained by KeyListener, only specified keys are allowed
- [key: string]: Array<0|1>
Found Bad Keys
- [symbol("0")]: [0,0,0,0]
- 1: [1,1,1,1]
*/
}
π Motivating Example
Playground link with relevant code
Certianly not DRY
π» Use Cases
EventEmitters, can't think of much else. But with how common event emitters are, this would be pretty great
Anything that loops over a keyof for type definition
Activity
[-]Bug: Extends doesn't constrain a generic type[/-][+]Feature: Extends doesn't constrain a generic type[/+]RyanCavanaugh commentedon Feb 4, 2022
See #14520
formula1 commentedon Feb 4, 2022
I didn't know what to call it but I like super, at typescript is aware of what people want. Overall, I'm pleased though.
thw0rted commentedon Feb 11, 2022
Hi Ryan Cavanaugh (@RyanCavanaugh) , you pointed to #14520 but no one from the team has been active on that issue. Could you please take a look? My post from last year has a lot of positive reaction.