【问题标题】:TypeScript - TS2322: Type 'string' is not assignable to type '"str1" | "str2"'TypeScript - TS2322:类型 'string' 不可分配给类型 '"str1" | "str2"'
【发布时间】:2020-09-04 07:43:17
【问题描述】:

我有一个函数,只能接受两个可能的值(用于验证)。为此,我这样做:

interface PossibleValues {
    key: "str1" | "str2";
}

我只能用 string 类型调用函数。这是我们的建筑设计,我必须处理它。

set({key: type})

因为 typestring 并且 key 只能接受 "str1" | "str2" 它说: TS2322:类型 'string' 不可分配给类型 '"str1" | "str2"' 说得通。

问题是如何以最优雅的方式克服这个问题?我的意思是我想传递一个 string 但如果该字符串不是两个 "str1" | "str2"

之一,则函数调用应该失败

我试图做的是: set({key: type} as PossibleValues) 并且它停止了抱怨,但没有达到预期的行为。例如,如果我通过“str333”,它仍然有效。

有什么想法吗?

【问题讨论】:

    标签: javascript typescript


    【解决方案1】:

    您需要意识到 TypeScript 只是为了帮助您解决编译时错误。它对运行时没有任何作用,因为它被编译为 JavaScript。类型和接口不存在。

    话虽如此,除非您对字符串进行硬编码以传递给 str1 | str2 这个函数,否则您不应该依赖 TypeScript 类型来确保它正常工作。

    您需要编写 JavaScript 检查代码并允许将任何字符串传递给函数。

    你可以创建一个类型保护来实现这个效果。

    https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types

    function isKey(value: string): value is "str1" | "str2" {
      return value === "str1" || value === "str2";
    }
    

    然后,你可以用它告诉 TypeScript 你已经检查了类型。

    if(isKey(type)) {
       set({ key: type }); // typescript won't complain anymore because you did a type check
    }
    

    【讨论】:

    • 我同意@Todd,尽管我认为这种检查应该是 set() 函数本身的一部分
    【解决方案2】:

    您需要使用该特定联合类型键入您命名为 type 的变量。

    type PossibleValue = 'str1' | 'str2'
    
    interface MyInterface {
        key: PossibleValue
        // ...
    }
    
    const set = (data: MyInterface) => { /* ... */ }
    
    let type: PossibleValue = 'str1' // OK
    type = 'str2' // OK
    type = 'str3' // Type '"str3"' is not assignable to type 'PossibleValue'.
    
    set({ key: type }) // OK
    set({ key: 'str3' }) // Type '"str3"' is not assignable to type 'PossibleValue'.
    

    Playground

    【讨论】:

      【解决方案3】:

      只需添加 Todd Skelton 的出色 answer,如果您使用的是 Typescript 3.4+,您可以使用以下语法定义您的类型保护:

      const keys = ['str1', 'str2'] as const
      type Key = typeof keys[number]
      const isKey = (s: string): s is Key => keys.some((k) => k === s)
      

      这种方法的好处是,如果您想添加/删除可能的值,您只需要修改 keys 数组。

      【讨论】:

        猜你喜欢
        • 2020-11-09
        • 1970-01-01
        • 1970-01-01
        • 2019-03-19
        • 2017-09-25
        • 2020-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多