I'd like to define the following types:
type Item = {
name: string,
value: number | string
}
type ItemFilter<T extends Item> = {
property: keyof Item;
value: // ?????? I'd like to have here the type of Item[property]
}
How can I set value
to have the type of item's property property?
I'd like to do the following:
const myItem: NumberItem = {
name: 'phoneNumber',
value: 1111111,
}
const valueFilter: ItemFilter<NumberItem> = {
property: 'value',
value: 11111, // SHOULD BE OK
}
const valueFilter: ItemFilter<NumberItem> = {
property: 'value',
value: 'STRING', // SHOULD FAIL
}
What I would do here is value constructor which would generate our proper filter value for our object. Consider the code:
const makeFilter = <T extends Record<string, any>> (item: T) => <K extends keyof T>(property: K, value: T[K]) => {
return {
property,
value
}
}
// TESTS
const myItem = {
name: 'phoneNumber',
value: 1111111,
}
const filter = makeFilter(myItem) // create function for specific object filtering
filter('value', 1231) // ok
filter('value', 'a') // error as expected
filter('name', 1231) // erorr as expected
filter('name', 'fine') // ok
Pay attention that we don't even need any Item
type anymore, solution will work with every object.
Some explanation:
makeFilter
is a function which derives types by arguments filter = makeFilter(obj)
creates our needed filter constructor for specific object filter
after has already proper narrowed types in the argumentsproperty: K, value: T[K]
means that value needs to be value of the object under the key - K
Function allows us for type inference over arguments, so we don't need to repeat redundantly types. We just make filter for wanted object.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.