I have the following function:
enum EventType {
First = 'first',
Second = 'second',
}
type First = {
first: string;
type: EventType.First;
};
type Second = {
second: string;
type: EventType.Second;
};
type Data = First | Second;
interface Options<T extends EventType = EventType> {
matcher: (data: Extract<Data, { type: T }>) => boolean;
type: T;
}
function foo(options: Options) {
...
}
I'm trying to achieve strict types on the matcher
functions data param based on the value of type
. For example with this usage:
foo({
matcher: data => ..., // data has type First
type: EventType.First,
});
foo({
matcher: data => ..., // data has type Second
type: EventType.Second,
});
My code doesn't achieve this, I think because it isn't clear where the generic T
takes it's value. Is it possible to do what I want?
CodePudding user response:
foo
must be made generic in order to allow Options
to correctly infer the type:
enum EventType {
First = 'first',
Second = 'second',
}
type First = {
first: string;
type: EventType.First;
};
type Second = {
second: string;
type: EventType.Second;
};
type Data = First | Second;
interface Options<T extends EventType = EventType> {
matcher: (data: Extract<Data, { type: T }>) => boolean;
type: T;
}
function foo<E extends EventType>(options: Options<E>) {}
foo({
matcher: data => true, // data has type First
type: EventType.First,
});
foo({
matcher: data => true, // data has type Second
type: EventType.Second,
});