TypeScript const断言:如何使用Array.prototype.includes? [英] TypeScript const assertions: how to use Array.prototype.includes?

查看:583
本文介绍了TypeScript const断言:如何使用Array.prototype.includes?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用元素数组作为联合类型,这在TS 3.4中通过const断言变得很容易,所以我可以这样做:

I am trying to use an array of elements as union type, something that became easy with const assertions in TS 3.4, so I can do this:

const CAPITAL_LETTERS = ['A', 'B', 'C', ..., 'Z'] as const;
type CapitalLetter = typeof CAPITAL_LETTERS[string];

现在,我想测试一个字符串是否为大写字母,但是以下操作失败,并显示无法分配给类型的参数":

Now I want to test whether a string is a capital letter, but the following fails with "not assignable to parameter of type":

let str: string;
...
CAPITAL_LETTERS.includes(str);

有没有比将CAPITAL_LETTERS强制转换为unknown然后强制转换为Array<string>更好的方法了?

Is there any better way to fix this rather than casting CAPITAL_LETTERS to unknown and then to Array<string>?

推荐答案

The standard library signature for Array<T>.includes(u) assumes that the value to be checked is of the same or narrower type than the array's elements T. But in your case you are doing the opposite, checking against a value which is of a wider type. In fact, the only time you would say that Array<T>.includes<U>(x: U) is a mistake and must be prohibited is if there is no overlap between T and U (i.e., when T & U is never).

现在,如果您不想经常使用includes()这种相反的"用法,并且希望零运行时效果,则应该通过类型断言将CAPITAL_LETTERS扩展为ReadonlyArray<string>:

Now, if you're not going to be doing this sort of "opposite" use of includes() very often, and you want zero runtime efects, you should just widen CAPITAL_LETTERS to ReadonlyArray<string> via type assertion:

(CAPITAL_LETTERS as ReadonlyArray<string>).includes(str); // okay

另一方面,如果您非常认真地认为应该接受不带任何类型断言的includes()用法,并且希望在所有代码中都使用它,则可以

If, on the other hand, you feel seriously enough that this use of includes() should be accepted with no type assertions, and you want it to happen in all of your code, you could merge in a custom declaration:

// global augmentation needed if your code is in a module
// if your code is not in a module, get rid of "declare global":
declare global { 
  interface ReadonlyArray<T> {
    includes<U>(x: U & ((T & U) extends never ? never : unknown)): boolean;
  }
}

只要数组元素类型和参数之间有一些重叠,它将使数组(嗯,这是一个只读数组,但这就是本例中的内容)将允许.includes()的任何参数类型.由于string & CapitalLetter不是never,它将允许呼叫.不过,它仍将禁止CAPITAL_LETTERS.includes(123).

That will make it so that an array (well, a readonly array, but that's what you have in this example) will allow any parameter for .includes() as long as there is some overlap between the array element type and the parameter type. Since string & CapitalLetter is not never, it will allow the call. It will still forbid CAPITAL_LETTERS.includes(123), though.

好的,希望能有所帮助;祝你好运!

Okay, hope that helps; good luck!

这篇关于TypeScript const断言:如何使用Array.prototype.includes?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆