typescript - 如何在通用占位符上使用提取
问题描述
bar 类的extend
守卫没有在 foo 类上强制执行。
Argument of type '"bar"' is not assignable to parameter of type 'Extract<keyof T, string>'.
酒吧中的 get 和 get2 调用。
class foo<T> {
get(a: Extract<keyof T, string>) {
return '';
}
}
interface IAttrs {
bar: boolean;
}
class bar<T extends IAttrs> extends foo<T>{
constructor() {
super();
this.get('bar')
this.get2('bar')
}
get2(a: Extract<keyof T, string>) {
return '';
}
}
class foobar extends foo<IAttrs>{
constructor() {
super();
this.get('bar')
}
}
我希望 bar 和 foobar 类都能编译;但是 bar 类有以下错误:
我正在使用打字稿 3.2.2
解决方案
主要问题是 whenT
是一个未解析的泛型类型参数,编译器不会(从 TS3.5 开始)执行它需要的类型分析,以便识别即使在被约束时"bar"
也可分配给 extend 。 是一种条件类型,编译器通常会推迟对未解析条件类型的大多数分析。也许这个特殊的用例可以作为建议提交到 GitHub,但我怀疑它会被优先考虑。Extract<keyof T, string>
T
IAttrs
Extract
所以我们需要要么使用已解析的条件类型,要么我们需要在非条件类型中使用未解析的类型参数。
已解析的条件类型:由于
keyof T
包含所有keyof IAttrs
,所以类型keyof T
等价于keyof T | keyof IAttrs
。所以Extract<keyof T | keyof IAttrs, string>
相当于有问题的类型。但由于Extract
是分布的,它会被评估为Extract<keyof T, string> | Extract<keyof IAttrs, string>
。最右边的成分是一个已解决的条件类型,它将被急切地评估为 just"bar"
。所以现在我们有了Extract<keyof T, string> | "bar"
. 未解决的条件类型仍然存在,但现在"bar"
明确地属于联合......并且错误应该消失。Unresolved non-conditional type:该
Extract
类型是在 TS2.8 中引入的,带有条件类型。它过滤带有约束的联合类型。在 TS2.8 之前,如果我们想约束这样的类型,我们只需要使用交集。过去,联合上的交叉点也很混乱,并且("foo" | "bar") & ("bar" | "baz")
会评估为("foo" & "bar") | ("foo" & "baz") | "bar" | ("bar" & "baz")
. 如今,尽管它根据需要减少到 just"bar"
。幸运的是,即使是未解析的类型参数也会在交集中进行分析......也就是说,如果X
已知可分配给A
和B
,则X
已知可分配给A & B
。所以我们可以更改Extract<keyof T, string>
为(keyof T) & string
,错误也应该消失。
让我们看看一些修改后的代码,它可以同时做这两个事情:
class Foo<T> {
// intersection
get(a: keyof T & string) {
return "";
}
}
interface IAttrs {
bar: boolean;
}
class Bar<T extends IAttrs> extends Foo<T> {
constructor() {
super();
this.get("bar");
this.get2("bar");
}
// resolved conditional
get2(a: Extract<keyof T | keyof IAttrs, string>) {
return "";
}
}
class FooBar extends Foo<IAttrs> {
constructor() {
super();
this.get("bar");
}
}
并且所有编译都没有错误。好的,希望有帮助;祝你好运!
推荐阅读
- python - Python3 中的 symtable 模块 - 为什么 Python3 中的 symtable.Symbol.is_global() 为顶层定义的符号返回 False?
- android - 如何让 Android 虚拟设备在 Linux 中识别 OBS 虚拟摄像头?
- python - 循环和搜索 Python
- lora - Lora 双工发送但收不到应答
- docker - 将日志轮换添加到现有容器而不重新创建
- python - 如何自动从另一个 List 的元素在 python 中创建列表
- go - 无法从 github 获取 gorose 2.0
- mysql - 无法在 MacBook Air 中的 mySQL 上运行模式
- javascript - 为什么 React 不显示来自组件的内容?
- javascript - 未捕获的 ReferenceError:在 __webpack_require__ 的 Object.babel-polyfill 中未定义 require