3

接口定义如下:

interface IRemoteService {
  createRecord(record: RecordType): ng.IPromise<ICreateResponse<string>>;
}

interface ICreateResponse<T> {
  createdId: T;
}

为什么以下代码不会导致 Typescript 编译错误?

class RemoteServiceMock implements IRemoteService {
  public static $inject = ["$q"];

  constructor(private $q: ng.IQService){
  }

  createRecord(record: RecordType): ng.IPromise<ICreateResponse<string>> {
    return this.$q.when({});
  }
}

的类型$q.whenwhen<T>(value: T): IPromise<T>

4

2 回答 2

3

这是根据规范。这是您的示例简化:

interface A{
}
interface B {
  createdId: string;
}

var foo:ng.IPromise<A>;
var bar:ng.IPromise<B>;
bar = foo; // No error

如果 A 是 B 的子类型或 B 是 A 的子类型,则允许此分配。如果不是这种情况,您将收到如下所示的错误:

interface A {
  breakTypeCompat: number;
}
interface B {
  createdId: string;
}

var foo:ng.IPromise<A>;
var bar:ng.IPromise<B>;
bar = foo; // Error

原因是函数参数的双变量兼容性。请参阅此链接了解文档 + 原因:https ://github.com/Microsoft/TypeScript/wiki/Type-Compatibility#function-argument-bivariance

细节

背景

接口的类型兼容性取决于您如何使用它们。例如,以下不是错误:

interface IPromise<T>{  
}

interface A{
}
interface B {
  createdId: string;
}

var foo:IPromise<A>;
var bar:IPromise<B>;
bar = foo; // No error

但是,如果IPromise使用类型参数作为成员的位置会出错:

interface IPromise<T>{
    member:T    
}

interface A{    
}
interface B {
  createdId: string;
}

var foo:IPromise<A>;
var bar:IPromise<B>;
bar = foo; // Error

所以

在实际的 Promise 定义中,我们有类似的内容:

interface IPromise<T> {
    then(successCallback: (promiseValue: T) => any): any;
}

interface A {
}
interface B {
    createdId: string;
}

var foo: IPromise<A>;
var bar: IPromise<B>;
bar = foo; // No Error

由于我们将T其用作 a函数 A的参数,并且B将通过双变量进行类型检查。因此,如果 A 是 B 的子集或 B 是 A 的子集,它们是兼容的。

于 2015-06-04T01:17:24.453 回答
1

我不确定你为什么没有收到错误,但我确实有关于如何获得警告的建议。根据 angular.d.tswhen定义如下:

when<T>(value: IPromise<T>): IPromise<T>;
when<T>(value: T): IPromise<T>;
when(): IPromise<void>;

因此,如果您想使用when更多类型,请使用:

return this.$q.when<ICreateResponse<string>>({});
于 2015-06-03T16:44:32.417 回答