Typescript 如何编写抽象类型脚本泛型类型?
鉴于以下类型Typescript 如何编写抽象类型脚本泛型类型?,typescript,generics,typescript-generics,Typescript,Generics,Typescript Generics,鉴于以下类型 接口基础{ id:字符串; } 接口A扩展了基础{ 普罗帕:弦; } 接口B扩展了基础{ propB:字符串; } 我想用以下约束条件表达一个通用的MyGeneric: T必须是对象 T键必须是string T值必须是基实例(要么是基类型,要么是扩展基类型) (3.wasT值必须与Base接口兼容,但已重新编写,以避免不理解) 我试过了 接口MyConstraint{ [键:字符串]:基 } 接口MyGeneric{ 数据:T } 但在这种情况下,当用户想要使用它时,它有两个缺
接口基础{
id:字符串;
}
接口A扩展了基础{
普罗帕:弦;
}
接口B扩展了基础{
propB:字符串;
}
我想用以下约束条件表达一个通用的MyGeneric
:
T
必须是对象T
键必须是string
T
值必须是基实例
(要么是基类型
,要么是扩展基类型)
(3.wasT
值必须与Base
接口兼容,但已重新编写,以避免不理解)接口MyConstraint{
[键:字符串]:基
}
接口MyGeneric{
数据:T
}
但在这种情况下,当用户想要使用它时,它有两个缺点:
type MyConstraint<T> = {
[K in keyof T]: T[K] extends Base ? T[K] : never;
};
interface MyGeneric<T extends MyConstraint<T>> {
data: T;
}
接口用户定义接口1{
a:a;
b:b;
}
函数foo1(p:MyGeneric):void{
//缺点1:这会引发TS2344:
//类型“userDefinedInterface1”不满足约束“userDefinedInterface1”。//类型“userDefinedInterface1”中缺少索引签名。
}
//要解决缺点1,用户必须扩展MyConstraint
接口userDefinedInterface2扩展了MyConstraint{
a:a;
b:b;
}
函数foo2(p:MyGeneric):void{
//缺点2:在这里,ts认为每个字符串属性都是有效的,因为[key:string]
console.log(p.data.arbirykey);//这是有效的
}
有没有办法定义
接口MyGeneric
以遵守上述3个约束条件而不存在这2个缺点?只有一个限制-如果要添加额外的键,必须指定它们
接口基础{
id:字符串;
num:数字;
}
接口A扩展了基础{
普罗帕:弦;
}
接口B扩展了基础{
propB:字符串;
}
类型MyGeneric={
数据:T&{
[key in K | keyof T]:key扩展了keyof T?T[key]:字符串;
}
}
常量test1:MyGeneric={
数据:{
id:'123',
总数:123,
建议B:‘123’,
测试:'123',
},
};
常量test2:MyGeneric={
数据:{
id:'123',
总数:123,
建议B:‘123’,
测试:“123”,//失败,必须在当前TS中提供。
},
};
如果您只想依靠T
的键
然后只需使用此版本:
类型MyGeneric={
数据:T&{
[key in keyof T]:key扩展keyof Base?Base[key]:字符串;
}
}
只有一个限制-如果要添加额外的密钥,必须指定它们
接口基础{
id:字符串;
num:数字;
}
接口A扩展了基础{
普罗帕:弦;
}
接口B扩展了基础{
propB:字符串;
}
类型MyGeneric={
数据:T&{
[key in K | keyof T]:key扩展了keyof T?T[key]:字符串;
}
}
常量test1:MyGeneric={
数据:{
id:'123',
总数:123,
建议B:‘123’,
测试:'123',
},
};
常量test2:MyGeneric={
数据:{
id:'123',
总数:123,
建议B:‘123’,
测试:“123”,//失败,必须在当前TS中提供。
},
};
如果您只想依靠T
的键
然后只需使用此版本:
类型MyGeneric={
数据:T&{
[key in keyof T]:key扩展keyof Base?Base[key]:字符串;
}
}
我认为这应该解决您的两个缺点:
type MyConstraint<T> = {
[K in keyof T]: T[K] extends Base ? T[K] : never;
};
interface MyGeneric<T extends MyConstraint<T>> {
data: T;
}
您会得到一个错误,指出属性类型
c
不兼容。我认为这应该解决您的两个缺点:
type MyConstraint<T> = {
[K in keyof T]: T[K] extends Base ? T[K] : never;
};
interface MyGeneric<T extends MyConstraint<T>> {
data: T;
}
如果使用
MyGeneric
,您会得到一个错误,说属性类型c
不兼容。它说如果使用MyGeneric
,则propB
永远不应该兼容:也许我当时误解了这个问题-我认为您的约束应该是一个对象,对象的值为Base
B
扩展了Base
,但它与您描述的T
类型(第3点)不匹配。他问:T必须是一个对象,T键必须是字符串,T值必须与基本接口兼容B
是一个对象,B
键是字符串,B
与Base
兼容,但是MyGeneric
不允许说string
应该是never
,这违反了第二个要求。似乎我使用了一个糟糕的措辞,导致了不理解。我认为@JánJakubNaništa做对了:我应该为第二个要求编写:T
值必须是instanceOf Base
(要么是类型基,要么是类型扩展基。我将用此更正编辑我的帖子。在这种情况下,如果我理解正确,B
不应该是MyGeneric
的有效类型参数,因为它的值没有扩展Base
正确吗?因此MyGeneric
确实应该给您一个错误。但是,例如MyGeneric
应该可以。那么我的答案正确吗?它说如果使用MyGeneric
就永远不应该使用propB
:也许我当时误解了这个问题-我认为你的约束应该是一个对象,对象的值应该是Base
。B
扩展Base
,但它与B
是一个对象,B
键是字符串,B
与Base
兼容,但是MyGeneric
不允许它说string
应该是永远不,这是错误的ks第二个要求。我似乎使用了一个糟糕的措辞,导致了不理解。我认为@JánJakubNaništa说得对:我应该为第二个要求编写:T
值必须是instanceOf Base
(要么是类型基,要么是类型扩展基。我将用此更正编辑我的帖子。在这种情况下,如果我理解正确,B
不应该是有效的类型argum