TypeScript未标记不兼容的泛型

TypeScript未标记不兼容的泛型,typescript,class,generics,types,interface,Typescript,Class,Generics,Types,Interface,我正在构建一个可插入的接口/类体系结构,以便“输出”可以插入“输入”。我很快发现,当我使用兼容的接口,但使用不兼容的泛型时,TypeScript不会抛出任何警告或错误。是否有我做错了的事情,或者我可以做更多的事情来强制进行正确的检查,或者这根本不受支持?打字稿2.9.2 interface IValueA { fooA(): void; } interface IValueB { barB(): void; } interface ISomethingA<T> { g

我正在构建一个可插入的接口/类体系结构,以便“输出”可以插入“输入”。我很快发现,当我使用兼容的接口,但使用不兼容的泛型时,TypeScript不会抛出任何警告或错误。是否有我做错了的事情,或者我可以做更多的事情来强制进行正确的检查,或者这根本不受支持?打字稿2.9.2

interface IValueA {
  fooA(): void;
}

interface IValueB {
  barB(): void;
}

interface ISomethingA<T> {
  goToB(thing: ISomethingB<T>): void;
}

interface ISomethingB<T> {
  goToA(thing: ISomethingA<T>): void;
}

interface ISomethingAS extends ISomethingA<string> {}
interface ISomethingAN extends ISomethingA<number> {}

interface ISomethingBS extends ISomethingB<string> {}
interface ISomethingBN extends ISomethingB<number> {}

export class SomethingA<T> implements ISomethingA<T> {
  public goToB(thing: ISomethingB<T>): void {
    console.log("SomethingA", "goToB", thing);
  }
}

export class SomethingAN implements ISomethingAN {
  public goToB(thing: ISomethingBN): void {
    console.log("SomethingA", "goToB", thing);
  }
}

export class SomethingAS implements ISomethingAS {
  public goToB(thing: ISomethingBS): void {
    console.log("SomethingA", "goToB", thing);
  }
}

export class SomethingB<T> implements ISomethingB<T> {
  public goToA(thing: ISomethingA<T>): void {
    console.log("SomethingA", "goToA", thing);
  }
}

export class SomethingBN implements ISomethingBN {
  public goToA(thing: ISomethingAN): void {
    console.log("SomethingA", "goToA", thing);
  }
}

export class SomethingBS implements ISomethingBS {
  public goToA(thing: ISomethingAS): void {
    console.log("SomethingA", "goToA", thing);
  }
}

const a = new SomethingA<IValueA>();
const b = new SomethingB<IValueB>();

const as = new SomethingAS();
const an = new SomethingAN();

const bs = new SomethingBS();
const bn = new SomethingBN();

a.goToB(b); // ISomethingA<IValueA> expects ISomethingB<IValueA> but accepts ISomethingB<IValueB>

as.goToB(bn); // ISomethingAS (ISomethingA<string>) expects ISomethingBS (ISomethingB<string>) but accepts ISomethingBN (ISomethingB<number>)
an.goToB(bs); // ISomethingAN (ISomethingA<number>) expects ISomethingBN (ISomethingB<number>) but accepts ISomethingBS (ISomethingB<string>)
接口IValueA{
fooA():void;
}
接口IValueB{
倒钩():空洞;
}
界面等距{
goToB(thing:isothingb):无效;
}
界面等距{
goToA(事物:等轴物):空虚;
}
接口ISomethingAS扩展ISomethingA{}
接口ISomethingAN扩展ISomethingA{}
接口ISomethingBS扩展ISomethingB{}
接口ISomethingBN扩展ISomethingB{}
导出类SomethingA实现了ISomethingA{
公共goToB(thing:isothingb):无效{
log(“SomethingA”,“goToB”,thing);
}
}
导出类SomethingAN实现了ISomethingAN{
公共goToB(thing:isothingbn):无效{
log(“SomethingA”,“goToB”,thing);
}
}
导出类SomethingAS实现了ISomethingAS{
公共goToB(thing:isothingbs):无效{
log(“SomethingA”,“goToB”,thing);
}
}
导出类SomethingB实现了ISomethingB{
公共goToA(thing:isothinga):无效{
log(“SomethingA”,“goToA”,thing);
}
}
导出类SomethingBN实现ISomethingBN{
公共goToA(thing:isothingan):无效{
log(“SomethingA”,“goToA”,thing);
}
}
导出类SomethingBS实现了ISomethingBS{
公共goToA(thing:isothingas):无效{
log(“SomethingA”,“goToA”,thing);
}
}
常数a=新事物a();
常数b=新事物b();
const as=新事物as();
const an=新事物();
const bs=新事物bs();
const bn=新事物bn();
a、 goToB(b);//ISomethingA期望ISomethingB,但接受ISomethingB
as.goToB(bn);//ISomethingAS(ISomethingA)期望ISomethingBS(ISomethingB),但接受ISomethingBN(ISomethingB)
A.goToB(bs);//ISomethingAN(ISomethingA)期望ISomethingBN(ISomethingB),但接受ISomethingB(ISomethingB)

如果需要错误,实际上应该对
ISomethingA
ISomethingB
中的某些内容使用通用
T
参数。如果只将其作为另一个泛型参数传递给其他对象,而从未实际使用过它,则不会出现错误,因为类型系统是结构化的,并且类型是兼容的

如中所述:“一般来说,您不应该有未使用的类型参数。该类型将具有意外的兼容性(如图所示),并且在函数调用中也无法进行正确的泛型类型推断。”

以下代码给出了您可能预期的错误:

interface IValueA {
  fooA(): void;
}

interface IValueB {
  barB(): void;
}

interface ISomethingA<T> {
    goToB(thing: ISomethingB<T>): void;
    t: T[];
}

interface ISomethingB<T> {
  goToA(thing: ISomethingA<T>): void;
    t: T[];
}

interface ISomethingAS extends ISomethingA<string> {}
interface ISomethingAN extends ISomethingA<number> {}

interface ISomethingBS extends ISomethingB<string> {}
interface ISomethingBN extends ISomethingB<number> {}

export class SomethingA<T> implements ISomethingA<T> {
  public goToB(thing: ISomethingB<T>): void {
    console.log("SomethingA", "goToB", thing);
  }
  t = [];
}

export class SomethingAN implements ISomethingAN {
  public goToB(thing: ISomethingBN): void {
    console.log("SomethingA", "goToB", thing);
  }
  t = [];
}

export class SomethingAS implements ISomethingAS {
  public goToB(thing: ISomethingBS): void {
    console.log("SomethingA", "goToB", thing);
  }
  t = [];
}

export class SomethingB<T> implements ISomethingB<T> {
  public goToA(thing: ISomethingA<T>): void {
    console.log("SomethingA", "goToA", thing);
  }
  t = [];
}

export class SomethingBN implements ISomethingBN {
  public goToA(thing: ISomethingAN): void {
    console.log("SomethingA", "goToA", thing);
  }
  t = [];
}

export class SomethingBS implements ISomethingBS {
  public goToA(thing: ISomethingAS): void {
    console.log("SomethingA", "goToA", thing);
  }
  t = [];
}

const a = new SomethingA<IValueA>();
const b = new SomethingB<IValueB>();

const as = new SomethingAS();
const an = new SomethingAN();

const bs = new SomethingBS();
const bn = new SomethingBN();

a.goToB(b); // error

as.goToB(bn); // error
an.goToB(bs); // error
接口IValueA{
fooA():void;
}
接口IValueB{
倒钩():空洞;
}
界面等距{
goToB(thing:isothingb):无效;
t:t[];
}
界面等距{
goToA(事物:等轴物):空虚;
t:t[];
}
接口ISomethingAS扩展ISomethingA{}
接口ISomethingAN扩展ISomethingA{}
接口ISomethingBS扩展ISomethingB{}
接口ISomethingBN扩展ISomethingB{}
导出类SomethingA实现了ISomethingA{
公共goToB(thing:isothingb):无效{
log(“SomethingA”,“goToB”,thing);
}
t=[];
}
导出类SomethingAN实现了ISomethingAN{
公共goToB(thing:isothingbn):无效{
log(“SomethingA”,“goToB”,thing);
}
t=[];
}
导出类SomethingAS实现了ISomethingAS{
公共goToB(thing:isothingbs):无效{
log(“SomethingA”,“goToB”,thing);
}
t=[];
}
导出类SomethingB实现了ISomethingB{
公共goToA(thing:isothinga):无效{
log(“SomethingA”,“goToA”,thing);
}
t=[];
}
导出类SomethingBN实现ISomethingBN{
公共goToA(thing:isothingan):无效{
log(“SomethingA”,“goToA”,thing);
}
t=[];
}
导出类SomethingBS实现了ISomethingBS{
公共goToA(thing:isothingas):无效{
log(“SomethingA”,“goToA”,thing);
}
t=[];
}
常数a=新事物a();
常数b=新事物b();
const as=新事物as();
const an=新事物();
const bs=新事物bs();
const bn=新事物bn();
a、 goToB(b);//错误
as.goToB(bn);//错误
A.goToB(bs);//错误