鑒于此處描述的示例 TypeScript mixin 模式:
type Constructor = new (...args: any[]) => {};
// This mixin adds a scale property, with getters and setters
// for changing it with an encapsulated private property:
function Scale<TBase extends Constructor>(Base: TBase) {
return class Scaling extends Base {
// Mixins may not declare private/protected properties
// however, you can use ES2020 private fields
_scale = 1;
setScale(scale: number) {
this._scale = scale;
}
get scale(): number {
return this._scale;
}
};
}
我們將如何顯式注釋Scale函式的回傳型別?即填寫???:
function Scale<TBase extends Constructor>(Base: TBase): ??? {
...
uj5u.com熱心網友回復:
您不需要為Scale函式聲明顯式回傳型別,因為 TypeScript 足夠聰明,可以推斷回傳型別。將滑鼠懸停在上面Scale,您將看到回傳型別為
{
new (...args: any[]): Scaling;
prototype: Scale<any>.Scaling;
} & TBase
此外,如果要為 使用顯式回傳型別Scale,則應Scaling在Scale函式外宣告(內部類)。像這樣:
class Scaling extends Base {
_scale = 1;
setScale(scale: number) {
this._scale = scale;
}
get scale(): number {
return this._scale;
}
}
function Scale<TBase extends Constructor>(Base: TBase) {
return Scaling
}
但那時Base應該是靜態的。
這意味著我們應該創建Mixin函式,就像在docs - Alternative Pattern 中一樣:
// credits goes to credits goes to https://stackoverflow.com/a/50375286
type UnionToIntersection<U> =
(U extends any ? (k: U) => void : never) extends (
k: infer I
) => void
? I
: never;
type ClassType = new (...args: any[]) => any;
function Mixin<T extends ClassType, R extends T[]>(...classRefs: [...R]):
new (...args: any[]) => UnionToIntersection<InstanceType<[...R][number]>> {
return merge(class { }, ...classRefs);
}
function merge(derived: ClassType, ...classRefs: ClassType[]) {
classRefs.forEach(classRef => {
Object.getOwnPropertyNames(classRef.prototype).forEach(name => {
// you can get rid of type casting in this way
const descriptor = Object.getOwnPropertyDescriptor(classRef.prototype, name)
if (name !== 'constructor' && descriptor) {
Object.defineProperty(
derived.prototype,
name,
descriptor
);
}
});
});
return derived;
}
class Foo {
tag = 'foo'
}
class Scaling extends Mixin(Foo) {
_scale = 1;
setScale(scale: number) {
this._scale = scale;
}
get scale(): number {
return this._scale;
}
}
const result = new Scaling();
result.tag // string
result.scale // number
您可以在medium和我的博客中找到我的文章分步說明。
UnionToIntersection- 創建聯合型別的交集。你可以在這個答案中找到完整的解釋
ClassType- 與您的Constructor. 它是任何類建構式的型別。
Mixin- 借助可變引數元組型別推斷引數中提供的每個類建構式,并將它們的所有實體合并到一個物件中UnionToIntersection<InstanceType<[...R][number]>>。
`[...R][number]` - takes a union of all provided class intstances
`InstanceType<[...R][number]>>` - replace every class constructor in the union
with class instance accordingly
`UnionToIntersection<InstanceType<[...R][number]>>` - merges all class instances
merge-applyMixins與檔案中的相同
更新
因為,Scaling是在函式內部定義的,所以不可能添加顯式回傳型別,Scaling因為它還不存在于作用域中。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/343875.html
上一篇:具有特定編號的函式多載
