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

基于键值约束对象的Typescript接口,typescript,react-redux,Typescript,React Redux,我是打字新手,一直在到处玩。我有一段出错的代码(为了简单起见删减了)。它最终用于redux操作/还原,这就是为什么它有点复杂的原因 interface StoreType { bool: boolean, num: number, } interface PayloadType { key: keyof StoreType, value: ??? } let test: PayloadType = { key: "bool", value: 3 // should i

我是打字新手,一直在到处玩。我有一段出错的代码(为了简单起见删减了)。它最终用于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'
问题分两部分:

  • 是否有可能在
    PayloadType
    中细化
    ,以便
    test.value
    类型为
    boolean
    如果
    test.key==“bool”
    ,类型为
    number
    如果
    test.key==“num”
    ?我尝试了
    value:StoreType[keyof StoreType]
    ,但没有充分约束:(

  • 有没有办法使作业
    obj[test.key]=test.value
    typesafe且无错误?我在中看到了错误,但我不确定如何继续,我不知道这是否与问题1有关

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


    谢谢!

    使用
    keyof-StoreType
    约束将
    PayloadType
    中的
    键定义为泛型类型参数
    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 // @ford04 looks as a good answer for the question you are asking, but not for a thing which your really want to achieve.

    There is no reason (or I don't see it) for having explicit type info in your payload. I would say you are revealing some technical details in place where the domain data should be revealed. So for me it is wrong approach.

    The sense in such would be to have discriminant in form of domain information:

    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});
    
    interface PayloadType{
    关键:K,
    值:StoreType[K]
    }
    let测试:PayloadType={
    键:“bool”,
    值:true//✅
    }
    let Tester错误:PayloadType={
    键:“bool”,
    
    value:3/@ford04看起来是你所问问题的好答案,但不是你真正想要实现的东西

    没有理由(或者我看不出来)在有效负载中有显式的类型信息。我想说的是,你在应该显示域数据的地方透露了一些技术细节。所以对我来说,这是错误的方法

    在这种意义上,将以域信息的形式具有歧视性:

    type ActionType='add_user'|'get_user'|'add_comment'|'get_comment'//动作类型示例
    //键入构造函数以保存我们键入的内容
    类型操作={
    类型:T,
    有效载荷:P
    }
    //具体行动
    键入UserId=number;//只是为了方便和可读性
    键入GetUserAction=Action
    type User={name:string}//示例有效负载类型
    输入AddUserAction=Action
    //动作创造者
    const getUser=(id:UserId):GetUserAction=>({type:'get_user',payload:id});
    

    负载也可以是主要类型,正如您在上面的示例中看到的
    get\u user
    操作。这种方法是类型安全的,您不能用错误的负载类型发送
    get\u user
    操作。希望它能帮到您。

    您肯定看到了我正在尝试做的事情,我非常感谢您给出的示例,仍然在尝试找出Redux+类型!当我尝试进行一个通用的“set”操作时,有效负载类型kerfuffle出现了,比如:
    ({type:'set_setting',有效负载:{key,value})
    ,因此最终
    存储[payload.key]=payload.value
    。我希望将可能的键限制为存储中现有的键,但我一辈子都不知道如何将值限制为对应于键。也许这不可能,我应该让我的操作更具体。。。