为什么此代码不会导致TypeScript类型错误? [英] Why doesn't this code cause a TypeScript type error?

查看:154
本文介绍了为什么此代码不会导致TypeScript类型错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

接口定义如下:

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

interface ICreateResponse<T> {
  createdId: T;
}

以下代码为什么不引起Typescript编译错误?

Why doesn't the following code cause a Typescript compilation error?

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.when的类型是when<T>(value: T): IPromise<T>.

推荐答案

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

This is according to spec. Here is your example simplified:

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

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

如果A是B的子类型或B是A的子类型,则允许此分配.如果不是这种情况,则会出现如下所示的错误:

This assignment is allowed if A is a subtype of B or B is a subtype of A. If this is not the case you will get an error as shown below:

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

The reason is the bivariance compatibility of function arguments. See this link for docs + reason why this is the way it is: https://github.com/Microsoft/TypeScript/wiki/Type-Compatibility#function-argument-bivariance

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

Type compatibility of the interfaces depends upon how you use them. E.g. the following is not an error :

interface IPromise<T>{  
}

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

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

但是,如果IPromise在哪里将type参数用作成员,则会出错:

However if the IPromise where to use the type parameter as a member it would error:

interface IPromise<T>{
    member:T    
}

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

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

因此

在实际的承诺定义中,我们有类似以下内容:

Therefore

In the actual promise definition we have something like:

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用作函数的参数,因此AB将通过双方差检查类型.因此,如果A是B的子集或B是A的子集,则它们是兼容的.

Since we are using T as an argument to the a function A and B will be type checked by bivariance. So if A is a subset of B or B is a subset of A they are compatible.

这篇关于为什么此代码不会导致TypeScript类型错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆