[英]How to know if the email has already been registered in firebase authentication, javascript?
[英]Typescript Trait Implementation: how to let generic know it has been already been extended?
嗨,也许标题是不对的,但我已经尝试用我有限的知识来指出我遇到的问题。 如果不对,请帮助编辑它。
我正在尝试创建一些特征函数来镜像一个类。 更像是PHP特质。
我这样做的原因是
尝试使用相同的设置而不写两次。
像这里的minx功能https://www.typescriptlang.org/docs/handbook/mixins.html
实现类要求您首先将目标类声明为undefined或etc。
2。 不是父母和孩子。 它没有扩展。
编译后该功能运行良好,但我不知道如何解决TS错误。
TS无法解析B已经拥有A的方法和属性。
代码如下。
export const trait = ( Orig : any ) : ClassDecorator =>
< T extends Function >( Tgt : T ) : void => {
let _stats =
Object
.getOwnPropertyNames( Orig )
.filter( prop =>
prop != 'length'
&& prop != 'prototype'
&& prop != 'name'
)
;
for( let _stat of _stats )
Object.defineProperty(
Tgt
, _stat
, Object.getOwnPropertyDescriptor( Orig , _stat ) || {}
)
let _insts =
Object
.getOwnPropertyNames( Orig.prototype )
.filter( prop =>
prop != 'constructor'
)
;
for( let _inst of _insts )
Object.defineProperty(
Tgt.prototype
, _inst
, Object.getOwnPropertyDescriptor( Orig.prototype , _inst ) || {}
)
} ;
class A {
propA = 1 ;
static propB = 2 ;
} ;
trait( A )
class B {
PropC = 3 ;
static propD = 4 ;
} ;
console.log( B.propA ) ;
console.log( new B().PropB ) ;
我收到的错误就像
Property 'propA' does not exist on type 'typeof B'. Did you mean 'propD'?
[更新]
感谢@T'的帮助,经过长时间的尝试,我发现了如何做到这一点。
首先,在类型检查器下方。 合并静态和原型。
type mir< C , O > =
{
new( ... agrs : any ) :
Inst< C >
& { [ I in keyof InstanceType< O > ] ?: InstanceType< O >[ I ] ; }
}
& C
& { [ I in keyof O ] ?: O[ I ] ; }
;
其次,这是实现它的方法。
class orig {}
@trait( orig )
class tgt {}
// js will work here but ts error will ocurr.
// therefore extend the types as well.
const Tgt : mir< tgt , orig > = tgt ;
所以特性将在JS中工作,如果你使用TS需要写更多的配置类型。
我不会谈论实现,它对我不起作用,但问题是如何让类型进行锻炼。
装饰器不能改变类的类型,这是设计的。 但是,您可以使用函数来转换类的类型。
要合并类属性,我们可以使用一些条件和映射类型魔术。 解决方案:
type Constructor = new (...a: any[]) => any;
type Merge<TTrait extends Constructor, TTarget extends Constructor> =
(new(...a: ConstructorParameters<TTarget>) => InstanceType<TTrait> & InstanceType<TTarget>) & Pick<TTarget, keyof TTarget> & Pick<TTrait, keyof TTrait>
const trait = <TTrait extends Constructor>(Orig: TTrait) =>
<TTarget extends Constructor>(Tgt: TTarget) : Merge<TTrait, TTarget> => {
// perform patching
return Tgt as any; // assertion required
}
class A {
propA = 1;
static propB = 2;
};
const B = trait(A)(class {
PropC = 3;
static propD = 4;
});
console.log(B.propB);
console.log(B.propD);
console.log(new B().PropC);
console.log(new B().propA);
class C extends B {
}
一点解释:
我们需要采用将在TTrait
和TTarget
类型参数中捕获的两个类类型并合并它们。 要合并类型,我们需要一个新的构造函数类型,它返回两个实例类型的交集。 我们可以使用预定义的条件类型InstanceType<T>
来获取实例类型。 然后我们可以将它们相交以创建新的实例类型: InstanceType<TTrait> & InstanceType<TTarget>
构造函数还需要从TTarget
复制参数。 我们可以使用ConstructorParameters
从目标构造ConstructorParameters
中获取参数,并使用rest参数中的元组将它们分散回新的构造函数中 。
最后一步是添加每个类的静态,删除原始类中的构造函数。 我们可以使用Pick
执行此操作,它将选择所有命名属性,但不会选择构造函数或函数签名。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.