【问题标题】:Typescript type with keys strictly made of a string union type带有严格由字符串联合类型组成的键的打字稿类型
【发布时间】:2020-12-10 03:51:23
【问题描述】:

我需要创建一个具有多个属性的类型,其中每个属性都有自己的类型(即不能保证所有属性都具有相同的类型。我还需要确保所有属性名称都严格来自另一个字符串联合类型.

这是我需要实现的示例

type Operations = "create:op" | "update:op" | "delete:op";

// Next three type defs only to demonstrate that all of them are different and 
// they don't have any common ancestor, etc.
type CreateOperationParams = {
    foo: string
}

type UpdateOperationParams = {
    bar: boolean
}

type DeleteOperationParams = {
    baz: number
}

// All properties in this type must be from Operations
// and every item from Operations must be present here
// as a property
type OperationParams = {
    "create:op"?: CreateOperationParams | false
    "update:op"?: UpdateOperationParams | false
    "delete:op"?: DeleteOperationParams | false
}

如果OperationsParams完全是手动编码的,那么很容易犯这样的错误

type OperationParams = {
    // Property name is not one of Operations, a dot is used instead of a colon.
    // This case must raise TS error. Another error should be that the correct
    // value "create:op" is not present in type properties 
    "create.op"?: CreateOperationParams | false   
    ...
}

以上是我实际拥有的简化示例。我在Operations 中输入了大约 40 个不同的值,其中一些名称有点长,带有一些特殊字符,如冒号或点。我显然可以小心地将它们全部复制并粘贴到 OperationsParams 类型中,并为每个类型定义正确的类型,但出错的可能性非常高,尤其是当 Operations 更改时。

有什么方法可以实现我的场景,但强制OperationsParams 的每个属性都来自Operations 联合类型,并且不能添加其他属性?还要确保Operations 中的所有项目都作为类型属性出现在OperationsParams 中?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    这是捕捉你意图的类型:

    type OpParam = CreateOperationParams | UpdateOperationParams | DeleteOperationParams;
    type OperationParams = Partial<Record<Operations, OpParam | false>>
    

    我在您的示例中添加了false。 这是完整的代码 - The Playground

    我们在这里做的是:

    • 我们说我们需要一个包含来自Operations 类型的键的记录
    • 我们说值可以是可能的 Param 类型之一(我把它放到 OpParam 中)
    • 我们用 Partial 包装它以使属性可选

    【讨论】:

    • 不幸的是,这不是我想要的。我需要确保类型定义的属性,而不是这种类型的对象。另外,我宁愿避免在每个属性上使用联合类型,我宁愿为每个道具保留特定类型
    【解决方案2】:

    这可能符合您的标准吗?

    type CreateParams = {
      "create:op"?: {
        foo: string
      }
    }
    
    type UpdateParams = {
      "update:op"?: {
        bar: boolean
      }
    }
    
    type DeleteParams = {
      "delete:op"?: {
        baz: number
      }
    }
    
    type OperationParams = CreateParams & UpdateParams & DeleteParams;
    
    type Operations = keyof OperationParams;
    
    const goodParams: OperationParams = {
      "create:op": {
        foo: "hey"
      },
      "delete:op": {
        baz: 3
      },
      "update:op": {
        bar: true
      }
    }
    
    const brokenParams: OperationParams = {
      //shows a compiler error as requested
      "create.op": {
        foo: "hey"
      },
      "delete:op": {
        baz: 3
      },
      "update:op": {
        bar: true
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-28
      • 2020-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-05
      • 1970-01-01
      相关资源
      最近更新 更多