These are my types:
export type Mapping =
| {
type: 'ok';
data: Record<string, string>;
}
| {
type: 'error';
data: Error;
};
export type Payload<T> = Extract<Mapping, { type: T }>['data'];
export interface Callback<T> {
(data: Payload<T>): void;
}
export type Store = {
[K in Mapping['type']]: Set<Callback<K>>;
};
This is my code:
const storage: Store = {
ok: new Set(),
error: new Set(),
};
function store<T extends Mapping['type']>(
type: T,
callback: Callback<T>
): void {
storage[type].add(callback);
}
The error I get:
Argument of type 'Callback<T>' is not assignable to parameter of type 'Callback<"ok"> & Callback<"error">'.
Type 'Callback<T>' is not assignable to type 'Callback<"ok">'.
Types of parameters 'data' and 'data' are incompatible.
Type 'Record<string, string>' is not assignable to type 'Payload<T>'.
Type 'Record<string, string>' is not assignable to type 'Extract<{ type: "error"; data: Error; }, { type: T; }>["data"]'.
Type 'Record<string, string>' is missing the following properties from type 'Error': name, messagets(2345)
I want to achieve, that if some callback is stored in either storage.ok or storage.error can deal the correct parameter type. So I tried to use conditional types, to add more options for the callback parameter types easily. I think the error is in 'Callback<"ok"> & Callback<"error">' because it shouldn't be &. But where is the error? The storage has the correct type:
type Store = {
error: Set<Callback<"error">>;
ok: Set<Callback<"ok">>;
}
Edit: The problem comes from the .add function:
(method) Set<T>.add(value: Callback<"ok"> & Callback<"error">): Set<Callback<"ok">> | Set<Callback<"error">>
Where comes the & from?