Typescript 如何在通用占位符上使用提取

Typescript 如何在通用占位符上使用提取,typescript,generics,Typescript,Generics,bar类上的extend保护未在foo类上强制执行 Argument of type '"bar"' is not assignable to parameter of type 'Extract<keyof T, string>'. 类型为“bar”的参数不能分配给类型为“Extract”的参数。 用于酒吧中的get和get2调用 class-foo{ 获取(a:摘录){ 返回“”; } } 接口IAttrs{ 条形图:布尔型; } 类栏扩展了foo{ 构造函数(){ 超级()

bar类上的
extend
保护未在foo类上强制执行

Argument of type '"bar"' is not assignable to parameter of type 'Extract<keyof T, string>'.
类型为“bar”的参数不能分配给类型为“Extract”的参数。
用于酒吧中的get和get2调用

class-foo{
获取(a:摘录){
返回“”;
}
}
接口IAttrs{
条形图:布尔型;
}
类栏扩展了foo{
构造函数(){
超级();
this.get('bar'))
this.get2('bar'))
}
get2(a:摘录){
返回“”;
}
}
类foobar扩展了foo{
构造函数(){
超级();
this.get('bar'))
}
}
我希望bar和foobar类都能编译;但是bar类有以下错误:


我使用的是typescript 3.2.2

主要问题是,当
T
是一个未解析的泛型类型参数时,编译器不会(无论如何从TS3.5开始)执行识别
“bar”所需的类型分析
可分配给
提取
,即使
T
被限制为扩展
IAttrs
Extract
是一个编译器,并且编译器一般都是这样。也许这个特定的用例可以作为一个建议,但我怀疑它是否会被优先考虑

因此,我们需要要么使用已解析的条件类型,要么在非条件类型中使用未解析的类型参数

  • 解析条件类型:由于
    keyof T
    包括所有
    keyof IAttrs
    ,因此
    keyof T
    类型相当于
    keyof T | keyof IAttrs
    。因此
    Extract
    相当于有问题的类型。但由于
    Extract
    是,因此它将被评估为
    Extract | Extract
    。最右边的组成部分是一个已解析的条件类型,它将被急切地计算为“bar”。现在我们有了
    提取|“bar”
    。未解析的条件类型仍然存在,但现在
    “bar”
    显式地成为联合的一部分。。。错误应该会消失

  • 未解析的非条件类型:
    Extract
    类型是在TS2.8中使用条件类型引入的。它过滤具有约束的联合类型。在TS2.8之前,如果我们想要约束这样的类型,我们只需要使用。过去,工会的交叉点也是杂乱无章的,
    (“foo”;“bar”)和(“bar”;“baz”)
    将评估为
    (“foo”和“bar”)(“foo”和“baz”)“bar”(“bar”和“baz”)
    。如今,尽管它只达到了所需的
    “bar”
    。幸运的是,即使是未解决的类型参数也会在交叉口进行分析。。。也就是说,如果已知
    X
    可分配给
    A
    B
    ,则已知
    X
    可分配给
    A和B
    。因此,我们可以将
    Extract
    更改为
    (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");
  }
}
class-Foo{
//交叉口
get(a:T和字符串的键){
返回“”;
}
}
接口IAttrs{
条形图:布尔型;
}
类栏扩展了Foo{
构造函数(){
超级();
这个。得到(“酒吧”);
本条第2款(“bar”);
}
//解析条件
get2(a:摘录){
返回“”;
}
}
类FooBar扩展了Foo{
构造函数(){
超级();
这个。得到(“酒吧”);
}
}


所有的编译都没有错误。好吧,希望这会有帮助;祝你好运

我认为当
t
仍然是泛型时,编译器无法将条件类型
Extract
解析为有用的内容,即使您知道
keyof t
必须至少包含
“bar”
。我的建议是将
Extract
改为
Extract
,甚至
(keyof T)&string
@jcalz,如果您添加注释作为解决方案,我会接受。我用`(keyof T)&string`来学习。非常感谢。