我没有为您提供非冗余且类型安全的解决方案。你的AttributeTrait
我一直称之为相关记录类型 https://github.com/microsoft/TypeScript/issues/30581。这是一个可区分的联合体,其中某些代码对于联合体的每个成员都是安全的,但编译器无法看到它对于整个联合体来说是安全的,因为它失去了对联合体的跟踪。相关性在。。之间category
and trait
特性。
如果编写冗余代码,错误就会消失:
function incrementRedundant(action: AttributeTrait) {
switch (action.category) {
case "physical":
attributes[action.category].traits[action.trait]++;
return;
case "social":
attributes[action.category].traits[action.trait]++;
return;
case "mental":
attributes[action.category].traits[action.trait]++;
return;
}
}
但是,无论您如何尝试,您都无法将这些情况折叠成一行代码并让编译器为您验证安全性。这就是我提交的原因微软/TypeScript#30581 https://github.com/microsoft/TypeScript/issues/30581,以及我提交的原因之一微软/TypeScript#25051 https://github.com/microsoft/TypeScript/issues/25051。因为你不能要求编译器处理单行as if它被写在一个switch
/case
声明,我能想到的最好的办法就是使用类型断言 https://www.typescriptlang.org/docs/handbook/basic-types.html#type-assertions告诉编译器你比它更了解。
做到这一点的一种方法是撒一点谎并告诉编译器:attributes
实际上拥有所有trait
全部category
对象:
function increment(action: AttributeTrait) {
(attributes as
Record<AttributeTrait["category"], {
traits: Record<AttributeTrait["trait"], number>
}>
)[action.category].traits[action.trait]++;
}
这比冗余代码的类型安全性较差,但至少它可以让您继续前进。
好的,希望有帮助;祝你好运!
Playground 代码链接 https://www.typescriptlang.org/play/#code/MYewdgzgLgBAhlKAnAlgIwK5QKYRgXhgG8AoGcmABwAsBPCFYOAGwC5iyKvk4UoJ2pLsIrQk2MAHMo1dgEYANJxFcAJtgAeOVFFrylK4dDgBbFGDj7lwgL7WbB0SGAoWg69yS9+7w12DUcKgQJpYwih4qoWAolBjMCCjgVn4UcJSU2EFwYMDYKSp2XA7WJhJQbhyGPHwCValU2Eh5lFBJYAWp5jjMzCiSEnmdfgDutcPF9iQ2ANwkJLqZMACCiKiYOAAqXnwE1gA+9SJMOJIgSHowAOQ09IwsV3PVO1DsANbYtCAAZjCL2D94Gt0FhcAA6W4MJjMME1fhPChFCiHIQqE7YM4XdhXCDOVzMR6Rchw96fQH-QEIZAgnAQMG4lwsWEvCAI8hI8gookwdGYy5XMpgCoEtnCEkwD5fX4U35U9agumC4XM7ys+xzEigSCwODANrJFbAjbYbbeAhHHkIDHnfkM-FXRzEl7Y6KxeKJcBXabzb4YXL6sAwczAcRKgBK2FUftUOSgAApdQH2KtqcbTXwAJQWiBjKABGAJvXtMG8m1Z1HHOAQbAwABEkPuzFrrG5XDlNNwAG1E8XSxcALoq2rdovgIdQfsAaknosM4igGCQYFnFCY1brdpYzdbaSNCpHAZLVr5g7hEAPxbhU5nO-I88Xy+5a5rtaVW5bDSBqf3PbHfdop4sheY5XtOK4iPeS6inYdgkL6-rtEGuShuUhZJoa35bC85bWAme60vAEDchGoBIKoAA8Kbylh3idrW-61v2CgWs8qrsCR5wUVRHbplAdFwoxzFgBgJhoE0AB83I2JJXAZsBYBHqcNqAaq8njtecywUAA