静态分型和通用矛盾 [英] static typting and generic contravariance

查看:82
本文介绍了静态分型和通用矛盾的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请参见代码

Please see the code here It is in typescript, but due to the similarity with C# may be it is applicable to it too.

export class Promise<T> {
}
export interface IId{
    id:()=> string;
}
class Service {
    get(id:string): Promise<IId> { return }
}

export interface IUser extends IId{
    name: string
}

export interface IUserService{
    test:(d:string) => Promise<IUser>;
}

class UserService implements IUserService{

    constructor(private srv: Service){}

    test(d:string):Promise<IUser> {
        return this.srv.get("");
    }
}

说,我有一个框架服务函数get,该函数返回类型为IId的Promise.在我的自定义类中,我有一个方法,该方法定义为返回类型为IUser的Promise.我通过返回this.srv.get("")并返回了Promise<IId>犯了一个错误.但这与Promise<IUser>不兼容,因为IUser期望使用name字段.为什么没有错误?

say, I have a framework service function get which returns a promise of type IId. In my custom class, I have a method, which is defined to return a promise of type IUser. I made a mistake by returning this.srv.get(""), which returns Promise<IId>. But that should not be compatible with Promise<IUser> as IUser is expecting a name field. Why there is no error?

我对C#泛型不熟悉,这就是所谓的contravariance.阅读了一些文章,但无法绕开它.

I am not familiar with C# generics, and is this what called contravariance. Read some articles but couldn't wrap my head around it.

推荐答案

您的Promise类型为空并且不使用T,这两个问题确实很大. TypeScript使用结构化类型系统,因此空类型是所有类型的超类型,并且不使用其类型参数的泛型类型将实际上不对这些类型参数进行类型检查.

Your Promise type is empty and doesn't use T, both of which are really big problems. TypeScript uses a structural type system, so an empty type is a supertype of all types, and a generic type that doesn't use its type arguments will effectively not have type checking on those type parameters.

如果Promise使用其type参数,则会看到错误:

If Promise used its type argument, you would see an error:

export class Promise<T> {
    foo: T; // <- ADDED
}
export interface IId{
    id:()=> string;
}
class Service {
    get(id:string): Promise<IId> { return }
}

export interface IUser extends IId{
    name: string
}

export interface IUserService{
    test:(d:string) => Promise<IUser>;
}

class UserService implements IUserService{

    constructor(private srv: Service){}

    test(d:string):Promise<IUser> {
        // ERROR
        return this.srv.get("");
    }
}

尝试使用C#(名义类型系统)作为TypeScript(结构类型系统)的参考点不会很有效.

Trying to use C# (a nominal type system) as a reference point for TypeScript (a structural type system) isn't going to be very productive.

这篇关于静态分型和通用矛盾的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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