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

时间:2019-05-21 01:35:38

标签: typescript generics

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

Argument of type '"bar"' is not assignable to parameter of type 'Extract<keyof T, string>'.

用于bar中的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

1 个答案:

答案 0 :(得分:0)

主要问题是,当T是一个无法解析的泛型类型参数时,编译器(无论如何从TS3.5开始)不会执行识别{{即使"bar"受约束扩展Extract<keyof T, string>,也可以将1}}分配给TIAttrsconditional type,编译器通常是defers most analysis of unresolved conditional types。也许可以将此特定用例作为filed in GitHub的建议,但我怀疑它会被优先考虑。

因此,我们需要使用可解析的条件类型,或者需要在非条件类型中使用未解析的类型参数。

  • 已解析的条件类型:由于Extract包含所有keyof T,因此类型keyof IAttrs等效于keyof T。因此keyof T | keyof IAttrs等同于有问题的类型。但是由于Extract<keyof T | keyof IAttrs, string>distributive,它将被评估为Extract。最右边的组成部分是可解析的条件类型,将急切地将其评估为Extract<keyof T, string> | Extract<keyof IAttrs, string>。现在我们有了"bar"。尚未解决的条件类型仍然存在,但是现在Extract<keyof T, string> | "bar"明确地是联合的一部分……错误应该消失了。

  • 未解决的非条件类型:"bar"类型是在TS2.8中引入的,带有条件类型。它过滤带有约束的联合类型。在TS2.8之前,如果我们想约束这样的类型,我们只需要使用intersections。也曾经是联合的交集很杂乱,Extract的计算结果为("foo" | "bar") & ("bar" | "baz")。如今,它可以根据需要将reduced调整为("foo" & "bar") | ("foo" & "baz") | "bar" | ("bar" & "baz")。幸运的是,即使是未解析的类型参数也会在相交处进行分析……也就是说,如果已知"bar"可同时分配给XA,那么B也是已知的可分配给X。因此我们可以将A & B更改为Extract<keyof T, string>,错误也应该消失。

让我们看一下同时做这两个事情的一些修改后的代码:

(keyof T) & string

Playground link

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