【问题标题】:Ignoring generic type argument when the specifity is not needed in Typescript当 Typescript 中不需要特殊性时忽略泛型类型参数
【发布时间】:2021-12-31 08:08:09
【问题描述】:

假设我有一个类,其中包含精心设计的泛型类型参数,例如

class SomeStuff<T extends ElaborateStuff> {...}

在其他地方,我有一个带有 SomeStuff 参数的函数,例如

function doSimpleThings(stuff: SomeStuff<X>): void {...}

它独立于X 作为ElaborateStuff 的扩展的具体化身。以上是编译器抱怨的,因为X必须扩展ElaborateStuff。我会写

function doSimpleThings(stuff: SomeStuff<any>): void {...}

但随后 eslint 抱怨 any 的显式使用。除了关闭any 警告之外,还有其他方法吗?在 Java 中我会使用 &lt;?&gt;,Typescript 中是否有类似的语法?

【问题讨论】:

    标签: typescript generics


    【解决方案1】:

    TL;DR:打字稿中没有? 语法。如果你可以使用除any 之外的任何东西,这真的取决于你的泛型类型的变化,但你可能会使用any 类通常最终是不变的。

    从本质上讲,这是一个差异问题。如果您想了解更多信息,可以查看我的演讲here

    如果类是 co-varinat,您可以使用 ElaborateStuff 并且 SomeStuff 的任何实例化都将与它兼容,因为 SomeStuff&lt;ElaborateStuff&gt; 将是所有实例化的基类:

    type ElaborateStuff = {
        a: string
    }
    class SomeStuff<T extends ElaborateStuff> {
        getVStuff(): T {
            return null!;
        }
    }
    
    function doSimpleThingsElaborateStuff(stuff: SomeStuff<ElaborateStuff>): void { }
    
    
    doSimpleThingsElaborateStuff(new SomeStuff<{ a: "", }>()); //OK
    doSimpleThingsElaborateStuff(new SomeStuff<{ a: "", b: "",}>()); // OK
    
    function doSimpleThingsNever(stuff: SomeStuff<never>): void { }
    doSimpleThingsNever(new SomeStuff<{ a: "", }>()); // Error 
    doSimpleThingsNever(new SomeStuff<{ a: "", b: "",}>()); // Error
    

    Playground Link

    如果你的类是逆变的,你可以使用never 并且SomeStuff 的任何实例化都将与它兼容,因为SomeStuff&lt;never&gt; 将是所有实例化的基类:

    type ElaborateStuff = {
        a: string
    }
    class SomeStuff<T extends ElaborateStuff> {
        getStuff = (v: T): void  => null!
    }
    
    function doSimpleThingsElaborateStuff(stuff: SomeStuff<ElaborateStuff>): void { }
    
    doSimpleThingsElaborateStuff(new SomeStuff<{ a: "", }>()); // error
    doSimpleThingsElaborateStuff(new SomeStuff<{ a: "", b: "",}>()); //error
    
    function doSimpleThingsNever(stuff: SomeStuff<never>): void { }
    
    doSimpleThingsNever(new SomeStuff<{ a: "", }>()); // ok 
    doSimpleThingsNever(new SomeStuff<{ a: "", b: "",}>());// ok
    

    Playground Link

    但是,如果您的类型是不变的,则只能使用any。 Lint 规则很有用,但可以忽略any 也有很好的用例,例如本例。但是你应该知道这是类型不安全的,所以你不应该依赖编译器来检查任何涉及类型参数的操作:

    type ElaborateStuff = {
        a: string
    }
    class SomeStuff<T extends ElaborateStuff> {
        getStuff = (v: T): T  => {
            v.a.big(); // error if a is not there
            return v;
        }
    }
    
    function doSimpleThingsElaborateStuff(stuff: SomeStuff<ElaborateStuff>): void { }
    
    doSimpleThingsElaborateStuff(new SomeStuff<{ a: "", }>()); // error
    doSimpleThingsElaborateStuff(new SomeStuff<{ a: "", b: "",}>()); //error
    
    function doSimpleThingsNever(stuff: SomeStuff<never>): void { }
    
    doSimpleThingsNever(new SomeStuff<{ a: "", }>()); // error
    doSimpleThingsNever(new SomeStuff<{ a: "", b: "",}>());// error
    
    
    function doSimpleThingsAny(stuff: SomeStuff<any>): void {
        stuff.getStuff({}) // will trigger an error
        stuff.getStuff({ a: ""}).foo // error on foo access
    }
    
    doSimpleThingsAny(new SomeStuff<{ a: "", }>()); // ok
    doSimpleThingsAny(new SomeStuff<{ a: "", b: "",}>()); // ok
    

    Playground Link

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-05
      • 1970-01-01
      • 2021-10-24
      • 1970-01-01
      • 1970-01-01
      • 2016-12-05
      • 2018-02-04
      相关资源
      最近更新 更多