使用mixin的打字稿钻石
typescript diamond using mixin
我有一组类可以"naively"表示为菱形:
OneBase
/ \
OneDer TwoBase
\ /
TwoDer
[注意——由于@mitch 评论已更改名称。]
其实One
和Two
就是"base"类,除了OneDer
和[=之外还有几个不同的类 19=] 使用相同的模式派生自它们。假设 (OneBase,TwoBase)
在模块 base
中,而 (OneDer, TwoDer)
在模块 derived
.
中
另外 OneBase
s 包含一个结构 Part
,其中包含一个 TwoBase
实例;在 OneDer
中,等效结构应包含一个 TwoDer
实例。
我把TwoBase
转换成mixin,下面的代码可以编译:
模块base
:
export type Constructor<T> = new(...args: any[]) => T
export class One {
p: Part
constructor (readonly a: number) {}
}
export class TwoPre extends One {
constructor (readonly a: number, readonly c: M[]) {
super(a)
}
}
export function TwoMix<
T extends Constructor<TwoPre>> (Base: T): Constructor<TwoPre> {
class Two extends Base {
}
return Two
}
export const Two = TwoMix(TwoPre)
export interface Part {
u: typeof Two
}
模块 derived
:
import { Part, One, TwoMix } from './base'
export class OneDer extends One {
p: Part
}
export class TwoDerPre extends OneDer {
constructor (readonly a: number, readonly c: M[]) {
super(a)
}
}
export const TwoDer = TwoMix(TwoDerPre)
请注意,TwoPre
和 TwoDerPre
是必需的,因为 "naive" Two
具有与 One
不同的构造函数签名,并且 mixin 函数无法定义
一个构造函数。这有点痛苦,因为它不必要地增加了原型链——所以变通办法值得赞赏。除此之外,mixin
执行我想要的方法解析顺序。
真正的问题是当我试图强制执行 PartDer
与 Part
的区别时;此版本的模块 derived
无法编译:
import { Part, One, TwoMix } from './base'
export class OneDer extends One {
p: PartDer
}
export class TwoDerPre extends OneDer {
constructor (readonly a: number, readonly c: M[]) {
super(a)
}
}
export const TwoDer = TwoMix(TwoDerPre)
export interface PartDer extends Part {
u: typeof TwoDer
}
我收到以下错误:
src/derived.ts(13,14): error TS7022: 'TwoDer' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
src/derived.ts(15,3): error TS2502: 'u' is referenced directly or indirectly in its own type annotation.
我想知道为什么编译器在 base
中没有抱怨这个循环,而我却抱怨这个循环,我能做些什么呢?
NOTE 这是我能想到的表达问题的最短方式。当然,TwoDer
真的不仅仅是 mixin 的实例化,所以 derived
末尾的代码看起来更像是:
export class TwoDer extends TwoMix(TwoDerPre) {
}
export interface PartDer extends Part {
u: TwoDer
}
在这个版本中,我得到的错误略有不同:
src/derived.ts(17,6): error TS2304: Cannot find name 'TwoDer'.
src/derived.ts(17,6): error TS4033: Property 'u' of exported interface has or is using private name 'TwoDer'.
如果我将 PartDer
转换为使用 typeof TwoDer
我会得到原始错误:
export interface PartDer extends Part {
u: typeof TwoDer
}
我不太明白你想做什么,但 TypeScript 在这里丢失了一些类型信息:
export const TwoDer = TwoMix(TwoDerPre)
这引起了连锁反应。您可以通过添加一些类型信息来解决这个特定问题:
export const TwoDer: Constructor<TwoPre> = TwoMix(TwoDerPre)
这解决了 'u' is referenced directly or indirectly in its own type annotation.
混乱的问题。我不知道它是否让一切都适合你。
我有一组类可以"naively"表示为菱形:
OneBase
/ \
OneDer TwoBase
\ /
TwoDer
[注意——由于@mitch 评论已更改名称。]
其实One
和Two
就是"base"类,除了OneDer
和[=之外还有几个不同的类 19=] 使用相同的模式派生自它们。假设 (OneBase,TwoBase)
在模块 base
中,而 (OneDer, TwoDer)
在模块 derived
.
另外 OneBase
s 包含一个结构 Part
,其中包含一个 TwoBase
实例;在 OneDer
中,等效结构应包含一个 TwoDer
实例。
我把TwoBase
转换成mixin,下面的代码可以编译:
模块base
:
export type Constructor<T> = new(...args: any[]) => T
export class One {
p: Part
constructor (readonly a: number) {}
}
export class TwoPre extends One {
constructor (readonly a: number, readonly c: M[]) {
super(a)
}
}
export function TwoMix<
T extends Constructor<TwoPre>> (Base: T): Constructor<TwoPre> {
class Two extends Base {
}
return Two
}
export const Two = TwoMix(TwoPre)
export interface Part {
u: typeof Two
}
模块 derived
:
import { Part, One, TwoMix } from './base'
export class OneDer extends One {
p: Part
}
export class TwoDerPre extends OneDer {
constructor (readonly a: number, readonly c: M[]) {
super(a)
}
}
export const TwoDer = TwoMix(TwoDerPre)
请注意,TwoPre
和 TwoDerPre
是必需的,因为 "naive" Two
具有与 One
不同的构造函数签名,并且 mixin 函数无法定义
一个构造函数。这有点痛苦,因为它不必要地增加了原型链——所以变通办法值得赞赏。除此之外,mixin
执行我想要的方法解析顺序。
真正的问题是当我试图强制执行 PartDer
与 Part
的区别时;此版本的模块 derived
无法编译:
import { Part, One, TwoMix } from './base'
export class OneDer extends One {
p: PartDer
}
export class TwoDerPre extends OneDer {
constructor (readonly a: number, readonly c: M[]) {
super(a)
}
}
export const TwoDer = TwoMix(TwoDerPre)
export interface PartDer extends Part {
u: typeof TwoDer
}
我收到以下错误:
src/derived.ts(13,14): error TS7022: 'TwoDer' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
src/derived.ts(15,3): error TS2502: 'u' is referenced directly or indirectly in its own type annotation.
我想知道为什么编译器在 base
中没有抱怨这个循环,而我却抱怨这个循环,我能做些什么呢?
NOTE 这是我能想到的表达问题的最短方式。当然,TwoDer
真的不仅仅是 mixin 的实例化,所以 derived
末尾的代码看起来更像是:
export class TwoDer extends TwoMix(TwoDerPre) {
}
export interface PartDer extends Part {
u: TwoDer
}
在这个版本中,我得到的错误略有不同:
src/derived.ts(17,6): error TS2304: Cannot find name 'TwoDer'.
src/derived.ts(17,6): error TS4033: Property 'u' of exported interface has or is using private name 'TwoDer'.
如果我将 PartDer
转换为使用 typeof TwoDer
我会得到原始错误:
export interface PartDer extends Part {
u: typeof TwoDer
}
我不太明白你想做什么,但 TypeScript 在这里丢失了一些类型信息:
export const TwoDer = TwoMix(TwoDerPre)
这引起了连锁反应。您可以通过添加一些类型信息来解决这个特定问题:
export const TwoDer: Constructor<TwoPre> = TwoMix(TwoDerPre)
这解决了 'u' is referenced directly or indirectly in its own type annotation.
混乱的问题。我不知道它是否让一切都适合你。