【发布时间】:2021-04-15 17:12:07
【问题描述】:
在我的打字稿程序(下面的代码)中,我定义了两个基本类型(Player、State),然后是一些嵌套的 Record 类型用作映射。
然后,我在一个类型化函数中根据嵌套记录的现有实例创建这些记录之一的实例。
type Player = "1" | "2";
type State = "A" | "B" | "C";
type StateMapping = Record<State, State>;
type PlayerStateMappings = Record<Player, StateMapping>
type PlayerStates = Record<Player, State>;
const playerStateMappings: PlayerStateMappings = {
"1": {
"A": "B",
"B": "C",
"C": "A"
},
"2": {
"C": "B",
"B": "A",
"A": "C"
},
}
function nextStates(currentState: State): PlayerStates {
var nextStates = {};
for(const player of Object.keys(playerStateMappings)){
nextStates[player] = playerStateMappings[player][currentState]
}
return nextStates;
}
console.log(nextStates("A"))
此代码在 return 语句中引发以下类型错误,因为我创建了没有所需键的对象,并且之后才添加了这些:
TS2739: Type '{}' is missing the following properties from type 'PlayerStates': 1, 2.
我的问题是,是否有一种方法可以避免满足以下要求的此类错误:
- 类型系统并没有特别放松,它仍然强制
nextStates函数返回一个完整且有效的PlayerStates对象。 -
nextStates对象是基于playerStatesMapping对象的键以编程方式创建的,这意味着我不必再次对所有播放器进行硬编码。
在对 SO 进行一些研究后,我发现了一些避免错误的选项,但所有这些选项都违反了上述两个要求之一:
违反条件 1 的方法:
- 将 PlayerStates 类型设为局部:
type PlayerStates = Partial<Record<Player, State>>; - 使用
as关键字强制类型:var nextStates = {} as PlayerStates; (来自this问题)
违反条件 2 的方法:
- 在对象创建中为每个玩家设置一个默认值:
var nextStates = {"1": "A", "2": "B"}
我知道在上面的例子中整个打字有点过头了,但这是我在一个更复杂的项目中遇到的问题的高度简化/简化版本,上面的要求/期望更有意义。
PS:来自 python 背景,我想我正在寻找类似 @987654322@ 的东西,它允许我基于一些迭代来初始化一个新字典。
【问题讨论】:
-
为什么“使用关键字强制类型”违反第 1 点? IMO 没有。
-
@hackape:因为那时类型系统不会强制我返回完整的
PlayerStates记录。例如,下面的代码会进行类型检查:``` function nextStates(currentState: State): PlayerStates { var nextStates = {} as PlayerStates;返回下一个状态; } ```
标签: javascript typescript