Reputation: 650
I have an object with some fields, and I'm going to implement an update function, which can modify value of existed key in my object. How can I restrict the function to only accept the existed keys in object, and the new value's type must be the same as the original value.
const defaultData = {
name: '',
count: 0,
desc: '',
visited: false,
};
type DataType = typeof defaultData;
type Keys = keyof DataType;
let data = Object.assign({}, defaultData);
// after tried, I found out this works. But not quite understand it
function updateData<T extends Keys, P extends DataType[T]>(k: T, value: P){
data[k] = value;
}
updateData('name', 'hehe');
updateData('count', false);
I'm wondering whether this is the ONLY way to define the updateData
function. What is P extends DataType[T]
is? I tried to use <T extends Keys, P = DataType[T]>
, but it is invalid.
Upvotes: 1
Views: 92
Reputation: 215039
I guess you can do that in a more generic way, so that you don't have to write type DataType = typeof defaultData;
etc for every data type you want to update.
function updater<T extends {}>(data: T) {
return function <K extends keyof T>(key: K, value: T[K]) {
data[key] = value
}
}
This is a generic higher order function that creates an updater function for a specific data type. It can be used like this:
let myData = {
name: '',
count: 0,
};
let updateMyData = updater(myData);
updateMyData('name', 'hehe'); // ok
updateMyData('blag', 'hehe'); // fail
updateMyData('count', false); // fail
Upvotes: 1
Reputation: 250266
Your option is an ok one, a simpler one would be to not use the P
type argument at all as we don't care about the actual type passed in, we only care that is is compatible with DataType[T]
:
function updateData<T extends Keys>(k: T, value: DataType[T]){
data[k] = value;
}
The reason P extends DataType[T]
works while P = DataType[T]
does not is that they do very different things. P extends DataType[T]
means that P
need to be a subtype of DataType[T]
. P = DataType[T]
means that if P
can't be inferred, DataType[T]
should be used (but P
can be any type not necessarily a sub type of DataType[T]
)
Upvotes: 1