用于基于键值约束对象的Typescript接口



我是Typescript的新手,一直在玩。我有这样的代码,它得到了一个错误(为了简单起见,减少了(。它最终是为了一个redux动作/减速器,这就是为什么它有点复杂的原因。

interface StoreType {
bool: boolean,
num: number,
}
interface PayloadType {
key: keyof StoreType,
value: ???
}
let test: PayloadType = {
key: "bool",
value: 3 // should ideally fail if value is not a boolean 
}
var obj: StoreType = { bool: true, num: 3 }
obj[test.key] = test.value // ts(2322) Type 'number' is not assignable to type 'never'

由两部分组成的问题:

  1. 是否有可能在PayloadType中细化value,使得如果test.key == "bool",则test.valueboolean类型,如果test.key === "num",则为number类型?我尝试了value: StoreType[keyof StoreType],但没有足够的约束:(

  2. 有没有一种方法可以使分配obj[test.key] = test.value类型安全且无错误?我在中看到了错误https://github.com/microsoft/TypeScript/issues/31663,但我不确定如何继续,我不知道这是否与问题1有关。

如果我错过了一些基本的东西,我不会感到惊讶。

谢谢!

PayloadType中的key类型定义为具有keyof StoreType约束的泛型类型参数K即可:

interface PayloadType<K extends keyof StoreType> {
key: K,
value: StoreType[K]
}
let test: PayloadType<"bool"> = {
key: "bool",
value: true // ✅
}
let testError: PayloadType<"bool"> = {
key: "bool",
value: 3 // 💣
}
var obj: StoreType = { bool: true, num: 3 }
obj[test.key] = test.value

StoreType[keyof StoreType]不适用于本例,因为keyof StoreType解析为并集类型"bool" | "num"。并且在StoreType中查找"bool" | "num"将解析为这些密钥的所有可能的返回类型number | boolean

通过将key类型与PayloadType<"bool">一起声明为泛型类型参数K,可以表示需要StoreType的specifc键(而不是并集(。

游乐场

@ford04看起来是你所问问题的一个很好的答案,但不是你真正想要实现的事情。

没有理由(或者我看不出(在您的负载中有明确的类型信息。我想说,你揭示了一些技术细节的领域数据应该披露。所以对我来说,这是错误的做法。

这样的意义是以领域信息的形式进行判别:

type ActionType = 'add_user' | 'get_user' | 'add_comment' | 'get_comment' // example action types
// type constructor to save us typing
type Action<T extends ActionType, P> = {
type: T,
payload: P
}
// specific actions
type UserId = number; // just for convenience and readability
type GetUserAction = Action<'get_user', UserId>
type User = {name: string} // example payload type
type AddUserAction = Action<'add_user', User>
// action creator
const getUser = (id: UserId):GetUserAction   => ({type: 'get_user', payload: id});

Payload也可以是主要类型,正如您在上面的get_user操作示例中看到的那样。这种方法是类型安全的,不能用错误的有效负载类型发送get_user操作。希望能有所帮助。

最新更新