TypeScript-TS2322:类型'string'不可分配给类型'“ str1” | “ str2”'

时间:2020-09-03 20:20:34

标签: javascript typescript

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

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

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

set({key: type})

因为type string ,而key只能接受"str1" | "str2",它表示: TS2322:类型'string'不能分配给类型'“ str1” | “ str2””

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

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

我试图做的是: set({key: type} as PossibleValues)并停止抱怨,但未实现所需的行为。例如,如果我通过“ str333”,它仍然可以工作。

有什么想法吗?

3 个答案:

答案 0 :(得分:3)

您需要认识到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
}

答案 1 :(得分:0)

您需要使用特定的联合类型键入您命名为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

答案 2 :(得分:0)

添加到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数组。