I am trying to setup a typing where I want a specific type to be resolved from an object property:
interface SubjectA {
id: string
title: string
description: string | null
quantity: number
links: string[]
}
let subjectA: SubjectA = {
id: "abc",
title: "def",
description: null,
quantity: 45,
links: ["ghi", "jkl"],
}
executeProcessor(subjectA, {
processors: [
{
id: "title",
process: (should_be_infered_as_string) => {},
},
{
id: "description",
process: (should_be_infered_as_string_or_null) => {},
},
{
id: "quantity",
process: (should_be_infered_as_number) => {},
},
{
id: "links",
process: (should_be_infered_as_string_list) => {},
},
],
})
Here, I'd like my parameter of process callback to be infered as the type of the property that match the given id.
Making the interface for the processor's item is not difficult:
interface PropertyProcessor<T, K extends keyof T> {
id: K,
process: (value: T[K]) => void
}
However, I'm struggling with typing the processors attribute itself:
interface ItemProcessor<T> {
processors: PropertyProcessor<T, what_to_put_here_?>[]
}
So far, I've used keyof T as a replacement of what_to_put_here_?. But my parameters are now infered as any of the possible options (string | null | number | string[]).
I think my PropertyProcessor type should not have a generics K, and should determine itself the type of the process parameter:
interface PropertyProcessor<T> {
id: keyof T,
process: (value: T[same_as_id_type]) => void
}
But I don't known how to do this.
Thanks in advance for you're help.
CodePudding user response:
You can get typescript to do this by adding a type parameter that will be inferred as a tuple of keys, and then mapping that tuple using a mapped type back to the array of processors:
type ProcessorMap<T, K extends Array<keyof T>> = {
[P in keyof K]: PropertyProcessor<T, K[P] & keyof T>
}
function executeProcessor<T,P extends [keyof T] | (keyof T)[]>(item: T, processor: {
processors: ProcessorMap<T, P>
}) {
}
The constraint [keyof T] | (keyof T)[] makes P be inferred to a tuple. Then we use the mapped type ProcessorMap to map back to the tuple we actually want.
