简体   繁体   English

TypeScript争论一个接口与通用类型T不兼容,尽管T扩展了该接口

[英]TypeScript arguing that an interface is not compatible with generic type T, although T extends that interface

I ran into a peculiar behaviour. 我遇到了一种特殊的行为。 Better explained by code below or following this typescript playground link 可以通过下面的代码或此打字机游乐场链接更好地解释

namespace Play {
    export interface BasicInterface {
        prop: any
    }

    export class Worker { 
        work(): BasicInterface {
            return { prop: "Hello" }
        }
    }

    export class Foo<T extends BasicInterface> {
        constructor(
            public worker: Worker,
            public workerCb: (workerResult: T) => any
        ) {}
        execute(): Promise<T> {
            return new Promise(res => {
                // Argument of type 'BasicInterface' is not assignable to parameter of type 'T'.
                res( this.workerCb(this.worker.work()) )
            }
        }    
    }
}
const foo = new Play.Foo<Play.BasicInterface>(new Play.Worker(), res => res)
foo.execute().then(res => console.log(res))

The problem occurs at line 20 saying that 问题发生在第20行,表示

Argument of type 'BasicInterface' is not assignable to parameter of type 'T'. 类型“ BasicInterface”的参数不能分配给类型“ T”的参数。

which is weird because T is defined as T extends BasicInterface in the Foo class declaration, so it should be fully compatible with BasicInterface . 这很奇怪,因为T被定义为T extends BasicInterface在Foo类声明中T extends BasicInterface ,因此它应该与BasicInterface完全兼容。

So, question are: why is that and how to fix that? 所以,问题是:为什么要这样以及如何解决?

UPDATE I'm even more puzzled now because TS seems to be fine with this which is the same(-ish?) thing or I don't see how it's much different... 更新我现在更加困惑,因为TS似乎可以解决这个问题 ,这是相同的(-ish?),或者我看不出它有多大不同...

namespace Play {
    export interface BasicInterface {
        prop: any
    }
    export class Implmentor implements BasicInterface {
        prop = "Hello"
    }
    export class Foo<T extends BasicInterface> {
        constructor(thingy: T) { }
    }
}

new Play.Foo(new Play.Implmentor())
new Play.Foo({prop: "Yay!"})

This is a correct error. 这是一个正确的错误。

Your class's contract says that this code is legal: 您班级的合同规定此代码是合法的:

interface BetterInterface extends Play.BasicInterface {
    thing: string;
}

const foo = new Play.Foo<BetterInterface>(new Play.Worker(), res => res)
// Throws an exception because 'thing' is undefined
foo.execute().then(res => console.log(res.thing.toUpperCase))

But your implementation can't produce an arbitrary T , it just always produces BasicInterface . 但是您的实现不能产生任意的T ,它总是产生BasicInterface

See also Why can't I return a generic 'T' to satisfy a Partial<T>? 另请参见为什么我不能返回通用T来满足Partial <T>?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM