网站搜索

typescript - 检查字符串是否是联合类型的成员


为了避免类型转换,我想了解在何种情况下可以安全地确定给定值的类型。我可以像这样使用字符串枚举来做到这一点:

enum Category {
    circle = "circle",
    square = "square",
}

const isObjValue = (val: any, obj: any) => Object.values(obj).includes(val)

isObjValue('circle', Category) // true

但我该如何用字符串联合来做呢?

const Category = "circle" | "square"

const isValidCategory = (string) => {
  if (/* string is in Category */) {
    return string as Category
  }
}

仍在学习TS!

答案#1

如果你有一个动态值,你可以创建一个用户定义的类型保护,以缩小该值的类型。

type Category = "circle" | "square"

// User-defined type guard that narrows the s from string type
// to Category type if s is either "circle" or "square".
function isCategory(s: string): s is Category {
    return s === "circle" || s === "square"
}

const a: string = "some dynamic string"
if (isCategory(a)) {
    // a type here is Category
    console.log(a, "is Category")
} else {
    // a type here is string
    console.log(a, "is not Category")
}

答案#2

为了避免必须记住总是更新类型和“is”检查函数,你可以改用数组,让 TS 将其转换为联合类型:

const ALL_CATEGORIES = ["circle", "square"] as const;
type typedCategoryList = typeof ALL_CATEGORIES;
type Category = typedCategoryList[number]; // this compiles to 'circle' | 'square'

const isCategory = (value: string) : value is Category => {
   return ALL_CATEGORIES.includes(value as Category )
}