Typescript - 交叉类型中的冲突方法签名
Typescript - conflicting method signatures in intersection type
我使用 FeathersJS(很棒)但不幸的是,它不是用 TypeScript 编写的,因此必须单独编写和维护类型。
Here 是打字文件。其中,有一个 Service<T>
类型,看起来像:
export type Service<T> = ServiceOverloads<T> & ServiceAddons<T> & ServiceMethods<T>;
ServiceOverloads<T>
看起来像:
export interface ServiceOverloads<T> {
create(data: Array<Partial<T>>, params?: Params): Promise<T[]>;
create(data: Partial<T>, params?: Params): Promise<T>;
patch(id: NullableId, data: Pick<T, keyof T>, params?: Params): Promise<T>;
}
和 ServiceMethods<T>
看起来像:
export interface ServiceMethods<T> {
find(params?: Params): Promise<T[] | Paginated<T>>;
get(id: Id, params?: Params): Promise<T>;
create(data: Partial<T> | Array<Partial<T>>, params?: Params): Promise<T | T[]>;
update(id: NullableId, data: T, params?: Params): Promise<T>;
patch(id: NullableId, data: Partial<T>, params?: Params): Promise<T>;
remove(id: NullableId, params?: Params): Promise<T>;
}
如您所见,create
和 patch
方法应该会发生冲突,因为它们生成相同的 JavaScript.
为什么类型别名 Service<T>
可以编译,但在尝试实现时由于方法冲突而失败?如果我完全从每个接口复制方法并提供一个存根实现,那应该行得通吗?
在 TypeScript 中,intersection of types with function signatures corresponds to overloading those functions. From the relevant GitHub issue introducing intersection types:
Call and Construct Signatures
If A
has a signature F
and B
has a signature G
, then A & B
has signatures F
and G
in that order (the order of signatures matter for purposes of overload resolution). Except for the order of signatures, the types A & B
and B & A
are equivalent.
在您的情况下,ServiceOverloads<T> & ServiceMethods<T>
实际上是
{
create(data: Array<Partial<T>>, params?: Params): Promise<T[]>;
create(data: Partial<T>, params?: Params): Promise<T>;
create(data: Partial<T> | Array<Partial<T>>, params?: Params): Promise<T | T[]>;
patch(id: NullableId, data: Pick<T, keyof T>, params?: Params): Promise<T>;
patch(id: NullableId, data: Partial<T>, params?: Params): Promise<T>;
find(params?: Params): Promise<T[] | Paginated<T>>;
get(id: Id, params?: Params): Promise<T>;
update(id: NullableId, data: T, params?: Params): Promise<T>;
remove(id: NullableId, params?: Params): Promise<T>;
}
因此您需要在 create()
和 patch()
是重载方法而不是单签名方法的地方实现它。这是一个示例:
class ServiceImpl<T> {
create(data: Array<Partial<T>>, params?: Params): Promise<T[]>;
create(data: Partial<T>, params?: Params): Promise<T>;
create(data: Partial<T> | Array<Partial<T>>, params?: Params): Promise<T | T[]>;
create(data: Partial<T> | Array<Partial<T>>, params?: Params) : Promise<T> | Promise<T[]> {
return null!; // impl
}
patch(id: NullableId, data: Pick<T, keyof T>, params?: Params): Promise<T>;
patch(id: NullableId, data: Partial<T>, params?: Params): Promise<T>;
patch(id: NullableId, data: Pick<T, keyof T> | Partial<T>, params?: Params): Promise<T> {
return null!; // impl
}
// other methods
}
function getService<T>(): Service<T> {
return new ServiceImpl<T>(); // okay
}
希望对您有所帮助;祝你好运!
我使用 FeathersJS(很棒)但不幸的是,它不是用 TypeScript 编写的,因此必须单独编写和维护类型。
Here 是打字文件。其中,有一个 Service<T>
类型,看起来像:
export type Service<T> = ServiceOverloads<T> & ServiceAddons<T> & ServiceMethods<T>;
ServiceOverloads<T>
看起来像:
export interface ServiceOverloads<T> {
create(data: Array<Partial<T>>, params?: Params): Promise<T[]>;
create(data: Partial<T>, params?: Params): Promise<T>;
patch(id: NullableId, data: Pick<T, keyof T>, params?: Params): Promise<T>;
}
和 ServiceMethods<T>
看起来像:
export interface ServiceMethods<T> {
find(params?: Params): Promise<T[] | Paginated<T>>;
get(id: Id, params?: Params): Promise<T>;
create(data: Partial<T> | Array<Partial<T>>, params?: Params): Promise<T | T[]>;
update(id: NullableId, data: T, params?: Params): Promise<T>;
patch(id: NullableId, data: Partial<T>, params?: Params): Promise<T>;
remove(id: NullableId, params?: Params): Promise<T>;
}
如您所见,create
和 patch
方法应该会发生冲突,因为它们生成相同的 JavaScript.
为什么类型别名 Service<T>
可以编译,但在尝试实现时由于方法冲突而失败?如果我完全从每个接口复制方法并提供一个存根实现,那应该行得通吗?
在 TypeScript 中,intersection of types with function signatures corresponds to overloading those functions. From the relevant GitHub issue introducing intersection types:
Call and Construct Signatures
If
A
has a signatureF
andB
has a signatureG
, thenA & B
has signaturesF
andG
in that order (the order of signatures matter for purposes of overload resolution). Except for the order of signatures, the typesA & B
andB & A
are equivalent.
在您的情况下,ServiceOverloads<T> & ServiceMethods<T>
实际上是
{
create(data: Array<Partial<T>>, params?: Params): Promise<T[]>;
create(data: Partial<T>, params?: Params): Promise<T>;
create(data: Partial<T> | Array<Partial<T>>, params?: Params): Promise<T | T[]>;
patch(id: NullableId, data: Pick<T, keyof T>, params?: Params): Promise<T>;
patch(id: NullableId, data: Partial<T>, params?: Params): Promise<T>;
find(params?: Params): Promise<T[] | Paginated<T>>;
get(id: Id, params?: Params): Promise<T>;
update(id: NullableId, data: T, params?: Params): Promise<T>;
remove(id: NullableId, params?: Params): Promise<T>;
}
因此您需要在 create()
和 patch()
是重载方法而不是单签名方法的地方实现它。这是一个示例:
class ServiceImpl<T> {
create(data: Array<Partial<T>>, params?: Params): Promise<T[]>;
create(data: Partial<T>, params?: Params): Promise<T>;
create(data: Partial<T> | Array<Partial<T>>, params?: Params): Promise<T | T[]>;
create(data: Partial<T> | Array<Partial<T>>, params?: Params) : Promise<T> | Promise<T[]> {
return null!; // impl
}
patch(id: NullableId, data: Pick<T, keyof T>, params?: Params): Promise<T>;
patch(id: NullableId, data: Partial<T>, params?: Params): Promise<T>;
patch(id: NullableId, data: Pick<T, keyof T> | Partial<T>, params?: Params): Promise<T> {
return null!; // impl
}
// other methods
}
function getService<T>(): Service<T> {
return new ServiceImpl<T>(); // okay
}
希望对您有所帮助;祝你好运!