我想根据与对象键相关的字符串的输入来更新对象的值,我应该如何使用 typescript 来实现这一点?
const objData = { // random value
A: 11,
B: 13,
C: 53,
innerObj: {
AStatus: true,
BStatus: false,
CStatus: true,
},
};
type Item = 'itemA' | 'itemB' | 'itemC';
function processObj(item: Item, obj: typeof objData) {
if (item === 'itemA') { // <- duplicate
obj.A = 5;
obj.innerObj.AStatus = true;
return obj;
}
if (item === 'itemB') { // <- duplicate
obj.B = 5;
obj.innerObj.BStatus = true;
return obj;
}
if (item === 'itemC') { // <- duplicate
obj.C = 5;
obj.innerObj.CStatus = true;
return obj;
}
return
}
processObj('itemA', objData);
例如,输入是itemA
,并且只有A
相关的objData被更新。
最佳答案
如果item
之间的关系obj
的参数和键名和obj.innerObj
通过字符串操作以编程方式确定,因此有一个属性键 k
的obj
对应属性k+"Status"
的obj.innerObj
并设置为值 "item"+k
的item
,那么你可以重构你的 processObj
使用函数template literal types 。模板文字类型允许您在类型级别表示一些字符串文字操作。这是一种方法:
type Keys = Exclude<keyof typeof objData, "innerObj">;
// type Keys = "A" | "B" | "C"
function processObj(item: `item${Keys}`, obj: typeof objData) {
const k = item.substring(4) as Keys; // need to assert here
obj[k] = 5;
obj.innerObj[`${k}Status`] = true;
return obj;
}
Keys
类型用途the Exclude<T, U>
utility type过滤 keys of objData
删除 "innerObj"
,留给我们 union "A" | "B" | "C"
.
对于其余部分,我们使用模板文字类型在类型级别执行字符串连接。 item
的类型是 `item${Keys}`
,其计算结果为 "itemA" | "itemB" | "itemC"
。我们可以计算出k
来自item
通过剥离最初的 "item"
来自它的前缀;结果的类型为Keys
,但编译器无法验证这一点。因此我们只是assert那k
类型为Keys
.
我们可以设置obj[k] = 5
没有编译器警告,因为编译器知道 obj
有一个number
Keys
中所有键的属性。我们还可以设置obj.innerObj[`${k}Status`] = true
没有编译器警告,因为编译器知道 template literal string value可以有一个模板文字类型,并且类型为 `${k}Status`
是 `${Keys}Status`
,其计算结果为 "AStatus" | "BStatus" | "CStatus"
。编译器知道 obj.innerObj
有一个boolean
这些键上的属性。
所以这一切都按预期进行。
另一方面,如果 item
之间的关系和obj
的 key 和obj.innerObj
是任意的,那么您不一定可以使用字符串操作来在它们之间进行映射。在这种情况下,您可能需要类似查找表的东西来表示映射,无论它是什么。这样的实现可能如下所示:
const propLookup = {
itemA: "A",
itemB: "B",
itemC: "C"
} as const;
const statusLookup = {
itemA: "AStatus",
itemB: "BStatus",
itemC: "CStatus"
} as const;
type Keys = keyof typeof propLookup;
// type Keys = "A" | "B" | "C"
function processObj(item: Keys, obj: typeof objData) {
obj[propLookup[item]] = 5;
obj.innerObj[statusLookup[item]] = true;
return obj;
}
propLookup
和statusLookup
对象只是来自有效 item
的映射值 obj
的相应属性和obj.innerObj
。他们正在使用 const
assertions所以编译器会跟踪字符串 literal types的值(value)观。如果我们停止as const
那么编译器会推断 string
对于值(value)观,这对我们没有帮助。
这也可以按需要工作;编译器理解 propLookup[item]
是 obj
的键与 number
值,并且 statusLookup[item]
是 obj.innerObj
的键与 boolean
值。
关于typescript - 如何根据 typescript 中的字符串输入更新对象数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71872370/