我遇到了函数过载的问题。编译器一直在选择错误的签名,我想知道为什么。
这里有一个显示行为的片段:Typescript Playground。作为参考,以下是代码段源:

class Query { }
class QueryInsert extends Query {
    constructor(public readonly objects?: any[], public readonly collection?: any) { super(); }
}
class QueryUpdate extends Query {
    constructor(public readonly object?: any, public readonly collection?: any, public readonly conditions?: any) { super(); }
}
class QueryShowCollection extends Query { }
class QueryCollectionExists extends Query {
    constructor(public readonly collection: any) { super(); }
}
class QueryDescribeCollection extends Query {
    constructor(public readonly collection: any) { super(); }
}
class QueryCreateCollection extends Query {
    constructor(public readonly collection: any, public readonly columns?: any[], public readonly indexes?: any[]) { super(); }
}
class QueryDropCollection extends Query {
    constructor(public readonly collection: any) { super(); }
}

function execute(query: QueryInsert): 'insert'
function execute(query: QueryUpdate): 'update'
function execute(query: QueryShowCollection): 'show'
function execute(query: QueryCollectionExists): 'exists'
function execute(query: QueryDescribeCollection): 'describe'
function execute(query: QueryCreateCollection): 'create'
function execute(query: QueryDropCollection): 'drop'
function execute(query: Query): any {

}

const insert = execute(new QueryInsert());
const update = execute(new QueryUpdate());
const show = execute(new QueryShowCollection());
const exists = execute(new QueryCollectionExists(''));
const describe = execute(new QueryDescribeCollection(''));
const create = execute(new QueryCreateCollection(''));
const drop = execute(new QueryDropCollection(''));

意外的行为来自结尾的常量。insert应报告"insert"update"update"等。
show之后,每个常数都会报告"show"
是的。我知道编译器为这些常量从function execute(query: QueryShowCollection): 'show'中选择签名。如果我们向下移动这个签名(例如:在带有querydropcollection的签名下面),那么它现在是function execute(query: QueryCollectionExists): 'exists'的,它将用于其余的常量。
我做了一些错误的事情。

最佳答案

问题是typescript使用结构兼容性来确定类型兼容性。在函数签名解析的情况下,编译器将对定义中的每个重载进行求值,以便从参数中找到参数query可赋值的第一个重载。
由于QueryShowCollection没有成员,因此它在结构上与所有其他Query*Collection类型兼容,这就是为什么您为所有集合获取show的原因。而且QueryDescribeCollectionQueryCollectionExists在结构上是相同的,您不能以区分两者的方式对重载进行排序。
你有两个解决方案
将重载从结构较复杂的排序到结构较不复杂的排序,以使编译器选择正确的覆盖
添加私有字段以确保类之间的类型不兼容。字段不必使用,只要存在即可。
第一个解决方案对您不起作用,因为您的一些类在结构上是相同的,所以第二个解决方案如下所示:

class Query { }
class QueryInsert extends Query {
    private type: 'insert';
    constructor(public readonly objects?: any[], public readonly collection?: any) { super(); }
}
class QueryUpdate extends Query {
    private type: 'update';
    constructor(public readonly object?: any, public readonly collection?: any, public readonly conditions?: any) { super(); }
}
class QueryShowCollection extends Query {
    private type: 'show';
}
class QueryCollectionExists extends Query {
    private type: 'exists';
    constructor(public readonly collection: any) { super(); }
}
class QueryDescribeCollection extends Query {
    private type: 'describe';
    constructor(public readonly collection: any) { super(); }
}
class QueryCreateCollection extends Query {
    private type: 'create';
    constructor(public readonly collection: any, public readonly columns?: any[], public readonly indexes?: any[]) { super(); }
}
class QueryDropCollection extends Query {
    private type: 'drop';
    constructor(public readonly collection: any) { super(); }
}

function execute(query: QueryInsert): 'insert'
function execute(query: QueryUpdate): 'update'
function execute(query: QueryDescribeCollection): 'describe'
function execute(query: QueryCreateCollection): 'create'
function execute(query: QueryDropCollection): 'drop'
function execute(query: QueryShowCollection): 'show'
function execute(query: QueryCollectionExists): 'exists'
function execute(query: Query): any {

}

const insert = execute(new QueryInsert());
const update = execute(new QueryUpdate());
const show = execute(new QueryShowCollection());
const exists = execute(new QueryCollectionExists(''));
const describe = execute(new QueryDescribeCollection(''));
const create = execute(new QueryCreateCollection(''));
const drop = execute(new QueryDropCollection(''));

关于typescript - Typescript函数重载不匹配,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49154574/

10-15 03:54