“字符串”类型的参数不可分配给字符串常量联合类型的参数

jav*_*mbk 7 typescript typescript-typings

我再次在这里寻求有关 Typescript 启发式的一些指导。我在编写类型保护时遇到了麻烦,因为 Typescript 在比较时想要太窄。

考虑以下场景(或Typescript Playground):

const FOO = 'foo' as const;
const BAR = 'bar' as const;

const ALL_THINGS = [FOO, BAR];
type AllThingsType = typeof ALL_THINGS[number];

function isAllThings(value: unknown): value is AllThingsType {
  return typeof value === 'string' && ALL_THINGS.includes(value);
}

Run Code Online (Sandbox Code Playgroud)

错误将如下所示:

Argument of type 'string' is not assignable to parameter of type '"foo" | "bar"'.ts(2345)

从技术上讲,有一种方法可以解决这个问题:

function isAllThingsWorkaround(value: unknown): value is AllThingsType {
  return typeof value === 'string' && (ALL_THINGS as string[]).includes(value);
}
Run Code Online (Sandbox Code Playgroud)

我是否遗漏了一些关于我应该如何做的事情?我分享的代码片段是一个简化版本,您可以假设它ALL_THINGS实际上是近 25 个常量的集合。我怎样才能改进这个以避免解决方法?

谢谢您的帮助!

小智 5

实现此目的的一种方法是不使用.includes.

const FOO = 'foo' as const;
const BAR = 'bar' as const;

const ALL_THINGS = [FOO, BAR];
type AllThingsType = typeof ALL_THINGS[number];

function isAllThings(value: unknown): value is AllThingsType {
  return typeof value === 'string' && ALL_THINGS.some(a => a === value);
}

console.log(isAllThings("cat")); // false
console.log(isAllThings("foo")); // true
Run Code Online (Sandbox Code Playgroud)

这种方式不需要类型转换,并且您可以决定“包含”的实际含义,而不是让 javascript 决定。

  • 我不确定为什么使用“includes”不起作用,如果这对我来说有意义,但我认为这种方法足够好,安全,并且完美地涵盖了这种情况。感谢您的建议。 (3认同)