In the following code, why is the callback assuming string | number | boolean
as the type instead of detecting the exact type based on the property that is being passed as the first argument of carWithListener.on
function?
const car = {
paint: "red",
tires: "mrf",
brakes: "disk",
bluetooth: true,
mileage: 7.45
}
type PropChangeListener<T> = {
on<Key extends string & keyof T>(
prop: `on${Capitalize<Key>}Changed`,
callback: (val: T[Key]) => T[Key]
): void
}
declare function registerForChanges<T>(obj: T): PropChangeListener<T>
const carWithListener = registerForChanges(car);
carWithListener.on("onBluetoothChanged", (val: boolean) => !val)
CodePudding user response:
You need to specify which key the listener is on
const car = {
paint: "red",
tires: "mrf",
brakes: "disk",
bluetooth: true,
mileage: 7.45
}
type PropChangeListener<T> = {
on<Key extends string & keyof T>(
prop: `on${Capitalize<Key>}Changed`,
callback: (val: T[Key]) => T[Key]
): void
}
declare function registerForChanges<T>(obj: T): PropChangeListener<T>
const carWithListener = registerForChanges(car);
carWithListener.on<'bluetooth'>("onBluetoothChanged", (val: boolean) => !val)
TS Playground: https://tsplay.dev/mAv1vW
The statement
callback: (val: T[Key]) => T[Key]
says, the callback
is a function that can take any of the type of the attributes of T. So, it can take string | number | boolean
unless you specify which key the listener is about.