Typescript 泛型可以有几个特定类型的约束而不进行扩展吗?
我的目标是使用严格的类型来确保对象的格式正确。我希望能够指定一些必须遵循的有效格式并加以实施Typescript 泛型可以有几个特定类型的约束而不进行扩展吗?,typescript,Typescript,我的目标是使用严格的类型来确保对象的格式正确。我希望能够指定一些必须遵循的有效格式并加以实施 interface TypeA { A: void; } interface TypeB { B: void; } interface TypeC { C: void; } type Type = TypeA | TypeB | TypeC; interface BaseItem<T extends Type> { name: string; data: T; } type Item
interface TypeA { A: void; }
interface TypeB { B: void; }
interface TypeC { C: void; }
type Type = TypeA | TypeB | TypeC;
interface BaseItem<T extends Type> { name: string; data: T; }
type Item = BaseItem<TypeA> | BaseItem<TypeB> | BaseItem<TypeC>;
const collection: Item[] = [
{ name: 'A', data: { A: null } },
{ name: 'B', data: { B: null } },
{ name: 'C', data: { C: null } },
];
class Example<T extends Type> {
item: BaseItem<T>;
add(item: BaseItem<T>) {
this.item = item;
collection.push(item); // Error on `item`
/**
* Argument of type 'BaseItem<T>' is not assignable to parameter of type 'Item'.
* Type 'BaseItem<T>' is not assignable to type 'BaseItem<TypeA>'.
* Type 'T' is not assignable to 'TypeA'.
* Type 'Type' is not assignable to type 'TypeA'.
* Property 'A' is missing in the type 'TypeB' but required in type 'TypeA'.
*/
}
}
接口类型A{A:void;}
接口类型B{B:void;}
接口类型C{C:void;}
类型=类型A |类型B |类型C;
接口BaseItem{name:string;data:T;}
类型项=基本项|基本项|基本项;
常量集合:项[]=[
{name:'A',数据:{A:null}},
{name:'B',数据:{B:null},
{name:'C',数据:{C:null},
];
课例{
项目:基本项目;
添加(项目:基本项目){
this.item=项目;
collection.push(item);//关于`item'的错误`
/**
*“BaseItem”类型的参数不能分配给“Item”类型的参数。
*类型“BaseItem”不可分配给类型“BaseItem”。
*类型“T”不可分配给“TypeA”。
*类型“Type”不可分配给类型“TypeA”。
*类型“TypeB”中缺少属性“A”,但类型“TypeA”中需要属性“A”。
*/
}
}
在上面的代码中,类型项
用于强制执行集合
数组中对象的格式。这让我了解了我计划如何使用这种格式
同样在上面的代码中,我尝试对示例
类使用泛型。我的想法是,我可能需要我的类的几个属性,以确保它们在任何给定时刻都使用共享泛型。尽管泛型扩展了有效类型,但我知道它在理论上可以支持它以外的类型(例如,BaseItem&{more:string}
)
我理解为什么它在当前状态下不工作。我不明白的是我将如何实现我想要的
有没有办法使用泛型来严格匹配一种类型的联合,而不是扩展一种类型的联合?比如,不是
,而是有类似
的东西吗?或者,有不同的方法来处理这个问题吗?我不知道如何将其分类,一个限制?但在我看来,这辆车有问题。以下是您可以修复它的方法:
interface TypeA { A: void; }
interface TypeB { B: void; }
interface TypeC { C: void; }
type Type = TypeA | TypeB | TypeC;
interface BaseItem<T extends Type> { name: string; data: T; }
type Item = BaseItem<TypeA> | BaseItem<TypeB> | BaseItem<TypeC>;
const collection: Item[] = [
{ name: 'A', data: { A: null } },
{ name: 'B', data: { B: null } },
{ name: 'C', data: { C: null } },
];
class Example<T extends Type> {
item: BaseItem<T>;
// notice this conditional type, see the irony here?
// everything `extends any`, so this expression reduce to
// just `BaseItem<T>`, never `never`, so why the trouble?
add(item: T extends any ? BaseItem<T> : never) {
this.item = item;
collection.push(item); // cus this way error magically disappear :)
}
}
接口类型A{A:void;}
接口类型B{B:void;}
接口类型C{C:void;}
类型=类型A |类型B |类型C;
接口BaseItem{name:string;data:T;}
类型项=基本项|基本项|基本项;
常量集合:项[]=[
{name:'A',数据:{A:null}},
{name:'B',数据:{B:null},
{name:'C',数据:{C:null},
];
课例{
项目:基本项目;
//注意这个条件类型,看到这里的讽刺了吗?
//everything'extensed any',因此此表达式简化为
//只是'BaseItem',从来没有'never',那么为什么会有麻烦呢?
添加(项:T扩展任何?基本项:从不){
this.item=项目;
collection.push(item);//这样错误会神奇地消失:)
}
}
我有点厌倦了使用TS时所涉及的所有技巧。这是,是的,又是一个花哨的名字,如果你感兴趣,请点击。就我个人而言,我不知道如何为这种行为辩护。你到底想解决什么问题?当前代码产生错误,因为
BaseItem
是Item
的子类型,而不是相反。我不明白为什么Type
有问题?如果你想t是Type
,那么你不需要一个通用的cus,你已经知道它是Type
。最终目标是使用t
类型使类具有多个属性和方法。这将允许任何子类更加具体(例如,特定于类的扩展示例{…}
),并强制遵守指定的任何类型,那么我就无法确保在一个应该只使用TypeA
的子类中,使用TypeA
而不是TypeB
。那么你已经得到了你想要的,
意味着你所说的
。正如我所说,您得到的错误与T
无关,我对TS处理泛型类型param的当前行为不满意。即使有这么强的约束,它也不能确定所有内容。链接让我意识到我可以使用该技术创建一个ItemByType
distributive条件类型,其值为T extends TypeA?BaseItem:…
用于所有项目类型。有点。。。冗长,但它有效。@KOVIKO upvote/accept如果能帮助您,那就太好了。我觉得我不能接受这个答案,因为我不确定在此上下文中使用any
的含义。但是投票是值得的!