简体   繁体   English

TypeScript 泛型类型推断

[英]TypeScript generic type infer

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.我有一个带有一些字段的 object,我将实施更新 function,它可以修改我的 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.如何限制 function 只接受 object 中存在的键,并且新值的类型必须与原始值相同。

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.我想知道这是否是定义updateData function 的唯一方法。 What is P extends DataType[T] is? P extends DataType[T]是什么? I tried to use <T extends Keys, P = DataType[T]> , but it is invalid.我尝试使用<T extends Keys, P = DataType[T]> ,但它无效。

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] :您的选择是好的,一个更简单的选择是根本不使用P类型参数,因为我们不关心传入的实际类型,我们只关心与DataType[T]兼容:

function updateData<T extends Keys>(k: T, value: DataType[T]){
    data[k] = value;
}

Play

The reason P extends DataType[T] works while P = DataType[T] does not is that they do very different things. P extends DataType[T]起作用而P = DataType[T]不起作用的原因是它们做了非常不同的事情。 P extends DataType[T] means that P need to be a subtype of DataType[T] . P extends DataType[T]意味着P需要是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] ) P = DataType[T]表示如果P无法推断,则应使用DataType[T] (但P可以是任何类型,不一定是DataType[T]的子类型)

I guess you can do that in a more generic way, so that you don't have to write type DataType = typeof defaultData;我想你可以用更通用的方式做到这一点,这样你就不必写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.这是一个通用的高阶 function,它为特定数据类型创建更新程序 function。 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

Play

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM